【问题标题】:Python error in basic subtraction? [duplicate]基本减法中的Python错误? [复制]
【发布时间】:2012-12-16 17:15:42
【问题描述】:

可能重复:
Python rounding error with float numbers
python maths is wrong

我无法让 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 做正确的算术运算。使用round(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}

【问题讨论】:

标签: python subtraction arithmetic-expressions


【解决方案1】:

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

对于初学者,请阅读floating point guide。长话短说:计算机将浮点数表示为二进制,事实证明,将精确的十进制小数存储为二进制是不可能的(try it for yourself 在纸上查看原因)。出于实际目的,0.19999999999999996 与 0.2“足够接近”。如果您想将其打印为 0.2,则可以执行以下操作:

print "%0.1f" % floating_point_value

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

【讨论】:

  • 谢谢。顺便说一句,doit() 的输出是字典,而不是整数,所以 print "%0.1f" % doit() 在这种情况下不起作用。
  • 你是对的。我已经更新了答案,使其更加明确。
  • 您对在使用 jq 时如何使用这项工作有什么建议吗?我将 jq 用于一个简单的数学函数,它为我提供了这些类似的输出来解决简单的问题。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    使用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
    

    【讨论】:

    • 为什么要输入浮点数?因此,第一个减法与 OP 有相同的问题。改用字符串:Decimal(1) - Decimal('0.8') -> Decimal('0.2')
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-16
    • 2015-06-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-25
    相关资源
    最近更新 更多