【发布时间】:2017-12-12 06:58:27
【问题描述】:
在研究python内置的float函数时,我阅读了the floating point doc。并有所了解。
- float 的实际值与其演示值不同,如
0.1的实际值为'0.1000000000000000055511151231257827021181583404541015625' - python 中的任何浮点数都有一个使用 IEEE-754 的固定值
- math.fsum 为我们提供了与输入的精确数学总和最接近的精确可表示值
但是在做了一堆实验之后,我还是遇到了一些未解的疑惑。
怀疑1
在我在第一段提到的教程文档中,它给了我们一个例子:
>>> sum([0.1] * 10) == 1.0
False
>>> math.fsum([0.1] * 10) == 1.0
True
根据文档的说明,我的印象是math.fsum 在进行浮点求和时会给我们一个更准确的结果。
但我在range(20) 中发现了一个特殊情况,其中sum([0.1] * 12) == 1.2 评估为True,同时math.fsum([0.1] * 12) == 1.2 评估为False。这让我很困惑。
为什么会这样?
以及sum在做浮点求和时的机制是什么?
怀疑2
我发现对于一些浮点计算,加法运算与其等效的乘法运算具有相同的效果。比如0.1+0.1+0.1+0.1+0.1等于0.1*5。但在某些情况下,并不等价,例如将0.1 加起来 12 次不等于 0.1*12。这让我真的很困惑。根据浮点数是由 IEEE-754 标准计算的固定值。根据数学原理,这种加法应该等于它的等值乘法。唯一的解释是python在这里没有完全应用数学原理,发生了一些棘手的事情。
但是这个棘手的东西的机制和细节是什么?
In [64]: z = 0
In [64]: z = 0
In [65]: 0.1*12 == 1.2
Out[65]: False
In [66]: for i in range(12):
...: z += 0.1
...:
In [67]: z == 1.2
Out[67]: True
In [71]: 0.1*5 == 0.5
Out[71]: True
In [72]: z = 0
In [73]: for i in range(5):
...: z += 0.1
...:
In [74]: z == 0.5
Out[74]: True
【问题讨论】:
-
我认为这可能是浮点数的原因,参考如下:stackoverflow.com/questions/2100490/…,如果你想避免这样的不准确,你可以尝试十进制数据类型。
-
因为您已经发现浮点数是不准确的,所以永远不要指望
==会起作用,即使数学告诉您它应该起作用,即使有时它确实起作用(“偶然”)跨度> -
@Julien,是的,困扰我的是浮点数上的加法不等于其等效乘法。这真的让我很困惑。你能给我一些提示,为什么会发生这种情况。是不是因为每次做加法时,中间的浮点结果都被四舍五入了?比如加0.1加12次,舍入12次,而
0.1*12只舍入一次? -
@Zen 没有“没有”理由为什么乘法应该给出与其重复加法“等效”相同的结果,因为它们遵循 2 个不同的路径/算法。虽然 x*y“是”x+x+x...y 次对于整数值,但这种解释对于非整数浮点数没有意义,因此这不是计算值的方式。
-
我可能不应该这样做,但请查看
for i in range(100): for j in (0.1, math.pi, math.e): assert i*j==math.fsum(i*[j])之类的内容:-]
标签: python python-3.x floating-point precision floating-accuracy