在 pandas 中四舍五入时更正浮点运算 'errors'

correcting for floating point arithmetic 'errors' when rounding in pandas

我有一个我讨厌的号码要处理(我相信还有其他号码)。

a17=0.0249999999999999
a18=0.02499999999999999

案例 1:

round(a17,2) gives 0.02
round(a18,2) gives 0.03

案例二:

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

案例 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.02, 0.02]

为什么我得到的答案和案例1一样?

当您使用浮点数时 - 您将无法获得精确值,但在大多数情况下只能得到近似值。由于浮点数的内存组织。

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

精确值只有“.”后的 17 位数字在 0.xxxx

这就是为什么:

>>> round(0.0249999999999999999,2)
0.03
>>> round(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.100000000000001和0.10000000000000000000055555151512312312578211211815815834045454115625都近似于3602879701896397 /2 ** 55的3602879701897 /2 ** 55均可享用任何一个相同的值。 ) == x.

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

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

For values exactly halfway between rounded decimal values, NumPy rounds to the nearest even value. Thus 1.5 and 2.5 round to 2.0, -0.5 and 0.5 round to 0.0, etc. Results may also be surprising due to the inexact representation of decimal fractions in the IEEE floating point standard [R9] and errors introduced when scaling by powers of ten.

结论:

在你的情况下 np.round 只是根据上述规则将 0.025 舍入为 0.02(来源 - NumPy 文档)