纠正浮点算术错误'当在熊猫中四舍五入

时间:2018-01-04 12:34:32

标签: python pandas floating-accuracy rounding-error

我有一个我必须处理的数字,我讨厌(我相信还有其他人)。

a17=0.0249999999999999
a18=0.02499999999999999

案例1:

round(a17,2) gives 0.2
round(a18,2) gives 0.3

案例2:

round(a17,3)=round(a18,3)=0.25

案例3:

round(round(a17,3),2)=round(round(a18,3),2)=0.03

但是当这些数字在数据框中时......

案例4:

df=pd.DataFrame([a17,a18])

np.round(df.round(3),2)=[0.2, 0.2]

为什么我得到的答案与案例1相同?

1 个答案:

答案 0 :(得分:2)

当您使用浮动时 - 您将无法获得EXACT值,但在大多数情况下仅接近。由于浮点数的内存组织。

你应该记住,当你打印浮动时 - 你总是打印近似的十进制!
这不一样。

“。”之后的确切值仅为17位数。在0.xxxx

这就是为什么:

  

>>>轮(0.0249999999999999999,2)
   0.03
  >>>轮(0.024999999999999999,2)
   0.02

大多数编程语言(Fortran,Python,C ++等)都适用

让我们看一下Python文档的片段:

https://docs.python.org/3/tutorial/floatingpoint.html

  

0.0001100110011001100110011001100110011001100110011 ...

停在任何有限数量的位上,你得到一个近似值。在今天的大多数机器上,浮点数使用二进制分数近似,分子使用前53位,从最高位开始,分母为2的幂。在1/10的情况下,二进制分数是3602879701896397/2 ** 55,它接近但不完全等于1/10的真实值。

由于显示值的方式,许多用户不知道近似值。 Python仅将十进制近似值打印到机器存储的二进制近似值的真实十进制值。在大多数机器上,如果Python要打印存储为0.1的二进制近似值的真实十进制值,则必须显示

  

>>> 0.1
    0.1000000000000000055511151231257827021181583404541015625

这比大多数人认为有用的数字更多,因此Python通过显示舍入值来保持可管理的位数

  

>>> 1/10    0.1

请记住,即使打印结果看起来像1/10的精确值,实际存储的值也是最接近的可表示二进制分数。

有趣的是,有许多不同的十进制数共享相同的最接近的近似二进制分数。例如,数字0.1和0.10000000000000001和0.1000000000000000055511151231257827021181583404541015625都近似为3602879701896397/2 ** 55.由于所有这些十进制值共享相同的近似值,因此可以显示其中任何一个,同时仍保留不变eval(repr(x) )== x。

让我们看一下NumPy文档的片段:

https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.around.html#numpy.around
要了解 - np.round使用np.around - 请参阅NumPy文档

  

对于正好在舍入小数值之间的值,NumPy舍入到最接近的偶数值。因此,由于IEEE浮点标准[R9]中的小数部分的不精确表示以及当以10的幂进行缩放时引入的误差,结果也可能是令人惊讶的1.5和2.5轮到2.0,-0.5和0.5轮到0.0等。

结论:

在你的情况下,np.round只是通过上述规则将0.025改为0.02(来源 - NumPy文档)