Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么'sum([0.1]*12)==1.2'是真的,而'math.fsum([0.1]*12)==1.2'是假的?_Python_Python 3.x_Floating Point_Precision_Floating Accuracy - Fatal编程技术网

Python 为什么'sum([0.1]*12)==1.2'是真的,而'math.fsum([0.1]*12)==1.2'是假的?

Python 为什么'sum([0.1]*12)==1.2'是真的,而'math.fsum([0.1]*12)==1.2'是假的?,python,python-3.x,floating-point,precision,floating-accuracy,Python,Python 3.x,Floating Point,Precision,Floating Accuracy,在研究python内置的浮点函数时,我阅读了以下内容。并且得到了一些理解 Float的实际值与其演示值不同,例如0.1的实际值为“0.10000000000000055551151231257827021181583404541015625” 使用IEEE-754,python中的任何浮点都有一个固定值 fsum为我们提供与输入的精确数学和最接近的精确表示值 但是在做了一系列的实验之后,我仍然遇到了一些尚未解决的疑问 怀疑1 在我在第一段提到的教程文档中,它给了我们一个示例: >>&

在研究python内置的浮点函数时,我阅读了以下内容。并且得到了一些理解

Float的实际值与其演示值不同,例如0.1的实际值为“0.10000000000000055551151231257827021181583404541015625” 使用IEEE-754,python中的任何浮点都有一个固定值 fsum为我们提供与输入的精确数学和最接近的精确表示值 但是在做了一系列的实验之后,我仍然遇到了一些尚未解决的疑问

怀疑1 在我在第一段提到的教程文档中,它给了我们一个示例:

>>> sum([0.1] * 10) == 1.0
False
>>> math.fsum([0.1] * 10) == 1.0
True
在博士的指导下,我得到了这样的印象:math.fsum在进行浮点求和时会给我们一个更准确的结果

但是我发现在20范围内有一个特例,其中sum[0.1]*12==1.2 evals True,而math.fsum[0.1]*12==1.2 evals False。这让我很困惑

为什么会这样? 当进行浮点求和时,求和的机制是什么

怀疑2 我发现对于一些浮点运算,plus运算与它的等价乘法运算具有相同的效果。例如0.1+0.1+0.1+0.1+0.1等于0.1*5。但在某些情况下,并没有等价物,比如0.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

当.1转换为64位二进制IEEE-754浮点时,结果正好是0.10000000000000055551151231257827021181583404541015625。当您将其单独添加12次时,在添加过程中会出现各种舍入错误,最终的总和正好是1.199999999999555910790149937383830547332763671875

巧合的是,当1.2转换为浮点时,结果也正好是1.199999999999555910790149937383830547332763671875。这是一个巧合,因为加法.1中的一些舍入错误向上舍入,一些舍入向下舍入,最终生成1.1999999999555910790149937383830547332763671875

但是,如果将.1转换为浮点,然后使用精确数学将其相加12次,则结果正好是1.200000000000000006661338147750939242541790008544921875。Python的math.fsum可能会在内部生成此值,但它不适合64位二进制浮点,因此将其四舍五入为1.200000000017763568394002504646778106689453125

如您所见,更精确的值1.200000000000000017763568394002504646778106689453125与将1.2直接转换为浮点值1.199999999999555910790149937383830547332763671875的结果不同,因此比较报告不相等


在中,我逐步增加了.1,以详细检查舍入误差。

我认为这可能是由于浮点数造成的,参考如下:,如果您想避免这样的不准确,可以尝试使用十进制数据类型。因为您已经发现浮点数不准确,因此,即使数学告诉你它应该工作,也不要期望==工作,即使有时它确实工作chance@Julien,是的,困扰我的是浮点数上的加法不等于它的等价乘法。这让我很困惑。你能告诉我为什么会发生这种事吗。是不是因为每次加法时,中间浮点结果都是四舍五入的?就像将0.1加12次,它被四舍五入12次,而0.1*12只被四舍五入一次?@Zen乘法没有理由给出与重复加法相同的结果,因为它们遵循两种不同的路径/算法。当x*y是x+x+x时。。。对于整数值的y倍,这种解释对于非整数浮点没有意义,因此,这不是计算值的方式。我可能不应该这样做,但请查看类似于范围100中的I:0.1中的j,math.pi,math.e:assert I*j==math.fsumi*[j]:-]