我在做作业时发现了这个有趣的问题我们知道,47.36/1.6**2 == 18.5
但是当我尝试运行以下代码时,它给了我一个 False(应该是真的)
打印47.36/1.6**2 == 18.5
有谁知道发生了什么?
你可能会得到一个答案,比如 18.49999999999,它并不完全等于 18.5。
与往常一样,这方面的相关参考是每个计算机科学家都应该知道的关于浮点运算的知识。
简短回答:IEEE 754 浮点不能精确表示分母不是 2 的幂的分数,例如 1/4、1/16、1/256 等。你可以非常接近,给定足够的数字,但永远不会完全在那里。
您可以通过将"等于"定义为"在某个增量内"来比较浮点数。你可以这样写:
def almost_equals(a, b, delta=0.0005):
return abs(a - b) <= delta
然后测试"可能等于":
>>> almost_equals(47.36/1.6**2, 18.5)
True
在比较两个浮点数时,我会避免检查完全相等。 相反,取差值,看看它是否小于您认为接近零的值。
(47.36/1.6**2 - 18.5) <0.00000000001
将是
真
>>> 47.36/1.6**2
18.499999999999996
请参阅此页面关于浮点运算:问题和限制。
以下是如何使用十进制模块在不使用任何舍入或"足够接近"行为的情况下将其精确计算18.5
:
>>> from decimal import Decimal
>>> Decimal('47.36') / Decimal('1.6')**2 == Decimal('18.5')
True
>>> float(Decimal('47.36') / Decimal('1.6')**2) == 18.5
True
正如其他人所说:
>>> 47.36/1.6**2
18.499999999999996
但是,据我所知,这不是由于浮点算术问题。 即使您通过将操作数包装在Decimal()
中使用十进制数学(在from decimal import Decimal
之后),您仍然会得到Decimal('18.49999999999999772404279952')
作为答案。
我可能在这里使用错误Decimal()
并且我的结果也有某种浮点误差;但是,如果我是对的,无论您使用哪种数学,该表达式都不等于18.5
。
编辑:正如 Greg 在评论中指出的那样,我在这里的方法的问题在于 Decimal(1.6) 只会将 1.6 的浮点表示(不完整)转换为十进制。这给出了正确的答案:
>>> Decimal('47.36') / Decimal('1.6')**2
Decimal('18.5')
更好的办法是按照柯克的建议使用分数模块。
47.36/1.6*2 返回整数。所以 47.36/1.6*2 将是 18,不等于 18.5。
编辑
抱歉,实际上它被存储为 18.499999。
你应该这样做
import numpy as np
print np.around((47.36/1.6**2), decimals=1) == 18.5
这将返回 True。