我使用 python 和 numpy 发现了这种奇怪的行为:
print('%10.3f' %0.4975)
返回 0.497,而
numpy.round(0.4975,3)
按预期返回 0.498。 对于其他类似的数字,我总是得到打印语句来提供正确舍入的值(例如:0.5975 --> 0.598)。 为什么是这样? 我在 Windows 7 上使用 python 3.4 和 numpy 1.9.2。
最佳答案
在 double 中,0.4975 是 8962163258467287/18014398509481984,比实数 0.4975 略小于。因此,Python 的 round
函数将其四舍五入为 0.497。
相比之下,0.5975 变为 5381801554707743/9007199254740992,比实数 0.5975 略更多。所以我们在四舍五入时得到了预期的 0.598。
为什么 NumPy 将 0.4975 舍入为 0.498?它的算法有点不同:要舍入到 N 位,它将给定数字乘以 10 的 N 次方,舍入到最接近的整数(最好是偶数),然后除以 10^N。在乘以10的幂的过程中,截断的方向发生变化;结果通常会得到一个半整数。 (示例:0.15*10 = 1.5 正好是 3/2,尽管 0.15 不正好是 3/20)。
简单来说,np.round(x, 3)
等同于round(x*1000)/1000
。您可以检查当应用于 x = 0.4975 时两者都返回 0.498。实际上,在 double 中,0.4975*1000 恰好 497.5(即 995/2),然后正确选择舍入方向。
以下是 0.05、0.15、0.25 等四舍五入方式的比较:
python
>>> [round((2*i+1)/20, 1) for i in range(10)]
[0.1, 0.1, 0.2, 0.3, 0.5, 0.6, 0.7, 0.8, 0.8, 0.9]
NumPy
>>> import numpy as np
>>> np.around([(2*i+1)/20 for i in range(10)], 1)
array([ 0. , 0.2, 0.2, 0.4, 0.4, 0.6, 0.6, 0.8, 0.8, 1. ])
这里的 NumPy 输出是人们在不考虑二进制表示的情况下所期望的。
然而,np.around([(2*i+1)/200 for i in range(100)], 2)
表明 NumPy 的算法并不总是符合预期,或者:有两个数字(0.55 和 0.57),末尾是奇数。问题是,例如,0.545*100 并不完全是 109/2;相反,它是 7670193115365377/140737488355328。
关于python - 格式化数值与舍入值之间的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38422170/