21

可能重复:
带有浮点数的 Python 舍入错误
python 数学是错误的

我无法让 Python 正确执行减法 1 - 0.8 并分配它。它不断地给出不正确的答案,0.19999999999999996。

我探索了一下:

sq = {}
sub = {}
for i in range(1000):
    sq[str(i/1000.)+'**2']=((i/1000.)**2)
    sub['1-'+str(i/1000.)]=(1.0-(i/1000.))

并发现此错误发生在 0 到 1 到小数点后第三位的随机浮点组中。当您对这些浮点数进行平方时,也会发生类似的错误,但对不同的子集。

我希望对此进行解释以及如何使 Python 正确地进行算术运算。Usinground(x,3)是我现在正在使用的解决方法,但它并不优雅。

谢谢!

这是我的 Python 2.7.3 shell 中的一个会话:

*** Python 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] on win32. ***
*** Remote Python engine  is active ***
>>> 1-0.8
0.19999999999999996
>>> print 1-0.8
0.2
>>> a = 1-0.8
>>> a
0.19999999999999996
>>> print a
0.2
>>> a = 0.2
>>> print a
0.2
>>> a
0.2
>>> 

这是我放入几个在线解释器的代码:

def doit():
    d = {'a':1-0.8}
    return d

print doit()

和输出:

{'a': 0.19999999999999996}
4

3 回答 3

17

使用Decimal它专门为此设计的:

>>> from decimal import Decimal, getcontext
>>> Decimal(1) - Decimal(0.8)
Decimal('0.1999999999999999555910790150')
>>> getcontext().prec = 3
>>> Decimal(1) - Decimal(0.8)
Decimal('0.200')
>>> float(Decimal(1) - Decimal(0.8))
0.2
于 2013-01-02T11:11:00.790 回答
12

浮动数字不像您期望的那样工作。

对于初学者,请阅读浮点指南。长话短说:计算机将浮点数表示为二进制,事实证明,将精确的小数部分存储为二进制是不可能的(在纸上亲自尝试一下,看看为什么)。出于实际目的,0.19999999999999996 与 0.2“足够接近”。如果您想将其打印为 0.2,那么您可以执行以下操作:

print "%0.1f" % floating_point_value

所以你看到的不是错误。这是预期的行为。

于 2013-01-02T10:24:54.810 回答
2

Python 存储带有“位”的浮点数,而有些浮点数无法准确表示,无论您有多少位精度。这就是你在这里遇到的问题。这有点像试图1/3用有限的小数位数完美准确地写成十进制。

于 2013-01-02T10:25:42.497 回答