我在做功课时发现了这个有趣的问题,我们知道,47.36/1.6**2 == 18.5
但是当我尝试运行以下代码时,它给了我一个 False(应该是真的)
打印47.36/1.6**2 == 18.5
有谁知道发生了什么?
您可能会得到类似 18.49999999999 的答案,它并不完全等于 18.5。
与往常一样,相关参考资料是What Every Computer Scientist Should Know About Floating-Point Arithmetic。
简短回答: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.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.5) < 0.00000000001
将会
真的
正如其他人所说:
>>> 47.36/1.6**2
18.499999999999996
但是,据我所知,这不是由于浮点算术问题。即使您通过将操作数包装在Decimal()
(之后from decimal import Decimal
)中来使用十进制数学,您仍然会得到Decimal('18.49999999999999772404279952')
答案。
我可能在Decimal()
这里用错了,我的结果也有某种浮点错误;18.5
但是,如果我是正确的,那么无论您使用哪种数学,该表达式都不等于。
编辑:正如格雷格在评论中指出的那样,我的方法的问题是 Decimal(1.6) 只会将 1.6 的浮点表示(不准确)转换为 Decimal。这给出了正确的答案:
>>> Decimal('47.36') / Decimal('1.6')**2
Decimal('18.5')
更好的是使用Kirk 建议的分数模块。
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。