Python数学精度

Python math accuracy

本问题已经有最佳答案,请猛点这里访问。

我在python中尝试了这个简单的数学运算

1
2
3
4
5
6
>>> math.floor(8.2-0.21)
7.0
>>> math.floor(8.21-0.2)
8.0
>>> math.floor(8.2-0.2)
7.0

第三个应该返回8,但它是返回7?!

更新

我在PHP、Ruby和Java中试用过,结果也一样。

更新2我不知道为什么这个问题会被否决!!


您引用的语言要么使用IEEE-754 64位二进制浮点,要么使用底层硬件的浮点,很可能是IEEE-754二进制浮点。

在IEEE-754 64位二进制浮点中,8.2的最近可表示值为8.19999999999928457264239899814128875732421875,而.2的最近可表示值为0.200000000000000111022302462515654404236316680908203125。

所以,当你写8.2 - 0.2时,实际发生的是,从8.1999999999999928457264239899814128875732421875中减去0.200000000000000111022302462515656404236316680908203125。结果是一个略低于8的值,而一个略低于8的值的下限是7。

这里的教训是浮点运算通常是近似的,因此在评估具有不连续性(如地板)或陡坡的函数时必须小心。您必须设计您的代码以接受可能跨越不连续的结果,或者您必须设计计算以避免跨越不连续的错误。


您的前两个示例是预期的:

  • 8.2 - 0.217.997.99的楼层是7层,这是返回的。记住,floor(x)是小于或等于x的最大整数。8大于7.99,不可能退货。另一方面,7满足这一要求。

  • 8.21 - 0.28.01。以东十一〔10〕楼是以东十一〔6〕楼,这里没有魔法。

1
2
>>> math.floor(8.2-0.2)
7.0

现在这更有趣了。这与8.20.2不能用float精确表示这一事实有关,因此计算结果可能不是您可能认为的那样:

1
2
>>> 8.2 - 0.2
7.999999999999999

同样,floor()也在按文件工作。

您可以使用decimal自己查看:

1
2
3
4
5
>> from decimal import Decimal
>>> Decimal(0.2)
Decimal('0.200000000000000011102230246251565404236316680908203125')
>>> Decimal(8.2)
Decimal('8.199999999999999289457264239899814128875732421875')

相关:每一个计算机科学家应该知道的关于浮点运算的知识


1
2
3
4
5
6
7
8
9
10
>>> a=0.2
>>> a
0.20000000000000001
>>> b = 8.2
>>> b
8.1999999999999993
>>> b-a
7.9999999999999991
>>> math.floor(b-a)
7.0

由于浮点误差


为什么应该是8?floor函数返回四舍五入的最接近整数,因此这两个示例是正确的。

8.2-0.21=7.99,四舍五入为7。

8.21-0.2=8.01,四舍五入为8。