Linux迷+Python粉 - 量化https://blog.pythonwood.com/2017-12-12T22:12:00+08:00Python量化之数据处理——小数浮点精度问题解决2017-04-18T14:03:00+08:002017-12-12T22:12:00+08:00pythonwoodtag:blog.pythonwood.com,2017-04-18:/2017/04/Python量化之数据处理——小数浮点精度问题解决/<h3 id="_1">量化金融刚结果:计算出差了一分钱的涨停价<a class="headerlink" href="#_1" title="Permanent link">¶</a></h3>
<p>量化金融用Python,最近在处理浮点问题的时候,发现一个问题,比较有意思,分享出来。</p>
<p>python计算79.035的四舍五入结果是79.03,这是错误的。</p>
<p>以下是IPython中输入程序语句,IPython能即时编译运算和输出结果。</p>
<div class="highlight"><pre><span></span># 计算71.85的涨停价
In [1]: 71.85 * 1 …</pre></div><h3 id="_1">量化金融刚结果:计算出差了一分钱的涨停价<a class="headerlink" href="#_1" title="Permanent link">¶</a></h3>
<p>量化金融用Python,最近在处理浮点问题的时候,发现一个问题,比较有意思,分享出来。</p>
<p>python计算79.035的四舍五入结果是79.03,这是错误的。</p>
<p>以下是IPython中输入程序语句,IPython能即时编译运算和输出结果。</p>
<div class="highlight"><pre><span></span># 计算71.85的涨停价
In [1]: 71.85 * 1.10
Out[1]: 79.035
# 涨停价四舍五入应该是79.04,但由精度损失,只有79.03。
In [2]: round(71.85 * 1.10, 2)
Out[2]: 79.03
</pre></div>
<h3 id="_2">原因分析<a class="headerlink" href="#_2" title="Permanent link">¶</a></h3>
<p>这个问题和Python语言本身无关,原因是浮点数即小数在<a href="http://www.cnblogs.com/jiayouwyhit/p/3148493.html" title="计算机的二进制化标准">计算机的二进制化标准</a>有关。</p>
<p>所以很多计算机语言都存在浮点精度损失问题,但庆幸python已有解决方法。Python已经写出了一些库,能屏蔽下层计算机架构带来的浮点问题。</p>
<h3 id="python">Python浮点运算的正确方法<a class="headerlink" href="#python" title="Permanent link">¶</a></h3>
<p>Python解决浮点精度问题的办法是使用<a href="http://python.usyiyi.cn/python_278/library/decimal.html" title="decimal官网">decimal</a>库。</p>
<div class="highlight"><pre><span></span><span class="n">In</span> <span class="p">[</span><span class="mi">26</span><span class="p">]:</span> <span class="kn">from</span> <span class="nn">decimal</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">In</span> <span class="p">[</span><span class="mi">31</span><span class="p">]:</span> <span class="k">print</span> <span class="n">Decimal</span><span class="p">(</span><span class="mf">79.035</span><span class="p">)</span><span class="o">.</span><span class="n">quantize</span><span class="p">(</span><span class="n">Decimal</span><span class="p">(</span><span class="s1">'.01'</span><span class="p">),</span> <span class="n">rounding</span><span class="o">=</span><span class="n">ROUND_HALF_UP</span><span class="p">)</span>
<span class="mf">79.04</span>
</pre></div>
<p>为此我特地写了邮件,写出期望优矿支持引入<a href="http://python.usyiyi.cn/python_278/library/decimal.html" title="decimal官网">decimal</a>库。得到回复说优矿下一个版本中引入。</p>
<p>(更新:到了5月份确实可以引入decimal库了,至此问题解决)</p>
<h3 id="_3">参考<a class="headerlink" href="#_3" title="Permanent link">¶</a></h3>
<p>谈谈关于Python里面小数点精度控制的问题 http://www.cnblogs.com/herbert/p/3402245.html</p>
<p>Python 为什么不解决四舍五入(round)的“bug”? https://www.zhihu.com/question/20128906</p>
<p>python:0.1 + 0.2 == 0.3:False https://stackoverflow.com/questions/588004/is-floating-point-math-broken</p>
<p>round() in Python doesn’t seem to be rounding properly https://stackoverflow.com/questions/56820/round-in-python-doesnt-seem-to-be-rounding-properly</p>