我是python的新手,我写的是:
t = 0.
while t<4.9:
t = t + 0.1
if t == 1.:
... do something ...
我注意到if语句从未被执行过。所以我修改了代码看起来像这样:
''' Case a'''
t = 0.
while t<4.9:
t = t + 0.1
print(t)
print(t == 5.)
当我跑步时,我得到:
>>> ================================ RESTART ================================
>>>
5.0
False
这是一个惊喜,因为我希望比较测试为True。然后,我尝试了以下两种情况:
''' Case b'''
t = 0
while t<5:
t = t + 1
print(t)
print(t == 5)
''' Case c'''
t = 0.
while t<5:
t = t + 0.5
print(t)
print(t == 5)
当我运行最后两个案例(b和c)时,最终语句中的比较测试为True。我不明白为什么会这样或为什么行为似乎不一致。我做错了什么?
答案 0 :(得分:7)
问题是二进制浮点运算不精确,因此在计算中会出现小错误。特别地,数字0.1没有精确的二进制表示。使用浮点数进行计算时,非常小的错误会导致结果与您的预期略有不同,这会导致相等测试失败。
使用默认字符串表示形式打印浮点数时,可能无法看到此小错误。请尝试使用repr
,因为这样可以更精确地表示数字(但仍然不是100%准确):
>>> print(repr(t))
4.999999999999998
>>> print(t == 5.)
False
要获得浮点数的准确字符串表示形式,您可以使用format
方法:
>>> print '{0:.60f}'.format(t)
4.999999999999998223643160599749535322189331054687500000000000
>>> print '{0:.60f}'.format(0.1)
0.100000000000000005551115123125782702118158340454101562500000
浮点运算的一般规则是永远不要进行相等比较。
当你使用0.5时它起作用的原因是因为0.5确实具有二进制浮点数的精确表示,因此在这种情况下你没有看到任何问题。同样,它适用于0.25或0.125。
如果您需要精确计算,则可以使用小数类型。
from decimal import Decimal
step = Decimal('0.1')
t = Decimal(0)
while t < Decimal(5):
t += step
print(t)
print(t == Decimal(5))
结果:
5.0 True
答案 1 :(得分:4)
从不尝试测试浮点数是否相等。
浮动通常是not exactly你输入的内容。
In [43]: .1
Out[43]: 0.10000000000000001
因此,仅测试具有不等式的浮点数会更安全。 如果您需要测试两个浮点数是否几乎相等,请使用近似的实用程序函数:
def near(a,b,rtol=1e-5,atol=1e-8):
try:
return abs(a-b)<(atol+rtol*abs(b))
except TypeError:
return False
rtol参数允许您指定相对容差。 (abs(a-b)/abs(b)) < rtol
atol参数允许您指定绝对容差。 abs(a-b) < atol
例如,你可以写
t = 0.
while t<4.9:
t = t + 0.1
if near(t,1.):
print('Hiya')