Python rounding error with float numbers
本问题已经有最佳答案,请猛点这里访问。
我不知道这是否是一个明显的错误,但是当运行一个用于改变模拟参数的python脚本时,我发现delta=0.29和delta=0.58的结果丢失了。在调查中,我注意到以下python代码:
1 2 3 4 5 6 | for i_delta in range(0, 101, 1): delta = float(i_delta) / 100 (...) filename = 'foo' + str(int(delta * 100)) + '.dat' |
为delta=0.28和0.29生成了相同的文件,与.57和.58相同,原因是python将float(29)/100返回为0.28999999999998。但这不是一个系统性的错误,不是说它发生在每个整数上。所以我创建了下面的python脚本:
1 2 3 4 5 6 7 | import sys n = int(sys.argv[1]) for i in range(0, n + 1): a = int(100 * (float(i) / 100)) if i != a: print i, a |
我看不到数字中出现这种舍入误差的模式。为什么这些特定的数字会发生这种情况?
任何不能用2的精确幂建立的数都不能精确地表示为浮点数;它需要近似。有时最接近的近似值会小于实际值。
阅读每个计算机科学家应该知道的关于浮点运算的知识。
由于浮点数的性质,它非常有名。
如果你想做十进制算术而不是浮点算术,有一些库可以做到这一点。
例如。,
1 2 3 4 5 6 7 | >>> from decimal import Decimal >>> Decimal(29)/Decimal(100) Decimal('0.29') >>> Decimal('0.29')*100 Decimal('29') >>> int(Decimal('29')) 29 |
一般来说,当数字没有有限的十进制表示时(例如分母不是1或分母不是2或5的任何分数-十进制基数(10)的因子),小数可能会出现舍入错误,并且在极少数情况下仍然会出现舍入错误。例如:
1 2 3 4 5 | >>> s = Decimal(7) >>> Decimal(1)/s/s/s/s/s/s/s*s*s*s*s*s*s*s Decimal('0.9999999999999999999999999996') >>> int(Decimal('0.9999999999999999999999999996')) 0 |
所以最好总是在将浮点值强制转换为整数之前进行取整,除非您希望使用floor函数。
1 2 3 4 | >>> int(1.9999) 1 >>> int(round(1.999)) 2 |
另一种选择是使用分数库中不近似的分数类。(它会根据需要不断地加减整数分子和分母)。