我今天花了一个小时试图找出原因
return abs(val-desired) <= 0.1
偶尔返回False
,尽管val
和desired
的绝对差异为<=0.1
。经过一些调试后,我发现了-13.2 + 13.3 = 0.10000000000000142
。现在我知道CPU不能轻易代表大多数实数,但这只是一个例外,因为你可以减去0.00000000000000142
并得到0.1
,所以它可以用Python表示。
我在Intel Core架构CPU上运行Python 2.7(这是我能够测试它的全部内容)。我很想知道如何能够存储0.1
的值,尽管无法将算术应用于特定的浮点值。 val
和desired
的值为float
。
答案 0 :(得分:4)
是的,这可能有点令人惊讶:
>>> +13.3
13.300000000000001
>>> -13.2
-13.199999999999999
>>> 0.1
0.10000000000000001
所有这些数字都可以用大约16位精度来表示。那么为什么:
>>> 13.3-13.2
0.10000000000000142
为什么在这种情况下只有14位精度?
嗯,那是因为13.3和-13.2有16位精度,这意味着14 小数点,因为小数点前有两位数。因此结果也有14 小数点的准确性。即使计算机可以代表16位数字。
如果我们将数字设得更大,结果的准确性会进一步降低:
>>> 13000.3-13000.2
0.099999999998544808
>>> 1.33E10-13.2E10
-118700000000.0
简而言之,结果的准确性取决于输入的准确性。
答案 1 :(得分:1)
“现在我明白CPU不能轻易代表大多数高分辨率的浮点数”,你问这个问题的事实表明你不明白。实数值13.2,13.3和0.1都不能完全表示为浮点数:
>>> "{:.20f}".format(13.2)
'13.19999999999999928946'
>>> "{:.20f}".format(13.3)
'13.30000000000000071054'
>>> "{:.20f}".format(0.1)
'0.10000000000000000555'
答案 2 :(得分:1)
要直接解决“我如何存储类似0.1的值并在我有不精确的浮点数时对其进行精确比较”的问题,答案是使用不同的类型来表示您的数字。 Python有一个decimal模块用于执行十进制定点和浮点数学而不是二进制 - 十进制,显然,0.1,-13.2和13.3都可以精确表示而不是近似;或者,您可以在使用低于该重要性级别的十进制和丢弃数字进行计算时设置特定的精度级别。
val = decimal.Decimal(some calculation)
desired = decimal.Decimal(some other calculation)
return abs(val-desired) <= decimal.Decimal('0.1')
另一种常见的替代方法是通过人工乘以10的幂来使用整数而不是浮点数。
return not int(abs(val-desired)*10)