"round"ed编号乘以0.01会产生x.y00000000000001而不是xy?

Cés*_*sar 3 python openerp

我问这个的原因是因为在OpenERP中有一个验证它让我发疯:

>>> round(1.2 / 0.01) * 0.01
1.2
>>> round(12.2 / 0.01) * 0.01
12.200000000000001
>>> round(122.2 / 0.01) * 0.01
122.2
>>> round(1222.2 / 0.01) * 0.01
1222.2
Run Code Online (Sandbox Code Playgroud)

如您所见,第二个round是返回一个奇数值.

有人可以向我解释为什么会这样吗?

bAr*_*don 8

这实际上没有任何关系round,如果您这样做,您可以看到完全相同的问题1220 * 0.01:

>>> 1220*0.01
12.200000000000001
Run Code Online (Sandbox Code Playgroud)

你在这里看到的是一个标准的浮点问题.

您可能想要阅读维基百科关于浮点精度问题的内容:

事实上,浮点数不能精确地表示所有实数,并且浮点运算不能精确地表示真正的算术运算,这会导致许多令人惊讶的情况.这与计算机通常表示数字的有限精度有关.

另见:

浮点数值不稳定的一个简单例子:数字是有限的.假设我们在给定计算机或语言中的点之后保存4位数.0.0001乘以0.0001会导致低于0.0001,因此无法保存此结果!在这种情况下,如果你计算(0.0001 x 0.0001)/ 0.0001 = 0.0001,这个简单的计算机将无法准确,因为它试图先加倍而后才加倍.在javascript中,除以分数会导致类似的不准确性.


Mar*_*ers 5

float您使用的类型存储二进制浮点数.并非每个十进制数都可以完全表示为a float.特别是没有1.2或0.01的精确表示,因此存储在计算机中的实际数字与源代码中写入的值略有不同.这种表示错误可能导致计算结果与精确的数学结果略有不同.

重要的是要注意每当使用浮点运算时出现小错误的可能性,并且即使计算出的值不完全正确,也要编写代码以使其工作正常.例如,在将值显示给用户时,应考虑将值四舍五入到一定数量的小数位.

您还可以考虑使用decimal存储十进制浮点数的类型.如果使用decimal那么1.2可以准确存储.但是,使用decimal会降低代码的性能.如果十进制数的精确表示很重要,则应该只使用它.你也应该意识到这decimal并不意味着你永远不会有任何问题.例如0.33333 ...没有确切的表示形式decimal.