在大熊猫舍入时纠正浮点算术'错误'

问题描述 投票:0回答:1

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

它是

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相同?

python pandas floating-accuracy rounding-error
1个回答
2
投票

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

你应该记住,当你打印浮动 - 你总是打印近似小数! 这不一样。

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

这就是为什么:

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

大多数编程语言都是如此(Fortran,Python,C ++等)

Let us look into fragment of Python documentation:

(Qazxswpoi)

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。

Let us look into fragment of NumPy documentation:

https://docs.python.org/3/tutorial/floatingpoint.html) 要了解 - np.round使用np.around - 请参阅NumPy文档

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

Conclusions:

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

© www.soinside.com 2019 - 2024. All rights reserved.