在 Pandas 中舍入时纠正浮点算术“错误”

Posted

技术标签:

【中文标题】在 Pandas 中舍入时纠正浮点算术“错误”【英文标题】:correcting for floating point arithmetic 'errors' when rounding in pandas 【发布时间】:2018-06-14 04:40:39 【问题描述】:

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

a17=0.0249999999999999
a18=0.02499999999999999

案例一:

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

案例 2:

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

【问题讨论】:

df.round(3) 的结果是什么? df=pd.DataFrame([a17,a18]) df.round(2) =0.02 但 df.round(3)=0.025 但 np.round(df.round(3),2 )=0.02 【参考方案1】:

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

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

“.”后的准确值只有 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.10000000000000000055511151231257827021181583404541015625

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

>>>1 / 10 0.1

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

有趣的是,有许多不同的十进制数共享相同的最接近的近似二进制分数。例如,数字0.1和0.10000000000000001和0.1000000000000000055511151231257827021181583404541015625都由2分之3602879701896397** 55.近似由于所有这些十进制值的共享相同的近似,可以同时仍保持不变的eval(再版(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 会四舍五入到最接近的偶数值。因此,1.5 和 2.5 舍入为 2.0,-0.5 和 0.5 舍入为 0.0,等等。由于 IEEE 浮点标准 [R9] 中小数部分的不精确表示以及按 10 的幂缩放时引入的错误,结果也可能令人惊讶。

结论:

在您的情况下,np.round 根据上述规则将 0.025 舍入到 0.02(来源 - NumPy 文档)

【讨论】:

感谢您的洞察力!最后一点是让我发疯的原因——为什么我不能在数据框中四舍五入?当我尝试对数据框进行舍入时,它无法完成,例如df=pd.DataFrame([a17,a18]) 然后 df.round(2) =0.02 但 df.round(3)=0.025 但 np.round(df.round(3),2)=0.02 我添加了 NumPy 文档和结论的片段 - 以帮助您理解。原因 - 只是 python 和 numpy 中的舍入规则不同。 对不起-我可以在一开始就描述它。我希望我回答了您关于当前主题的所有问题。 我认为这也与 numpy 回合中的错误有关。例如 np.round(0.024999,3) 在我的计算机上不会四舍五入到小数点后 3 位。它给出 0.025000000000001 马克,这不是错误。 :) 内存中的浮点数是一回事,打印的结果 - 不是浮点数 - 这是近似浮点数的两倍。只需仔细阅读答案(和链接)中的 python floats 文档。 :)

以上是关于在 Pandas 中舍入时纠正浮点算术“错误”的主要内容,如果未能解决你的问题,请参考以下文章

如何在 extjs4.1 中舍入浮点值

尝试从 Pandas DataFrame 中的字典访问第一个值时出现浮点错误

熊猫浮点错误

使用 Excel Pandas 中的浮点值填充字典的问题

导入 pandas_datareader 时遇到问题

TFS 签入时,提示“变更集注释策略 中的内部错误……”