格式化数值和舍入值之间的差异

时间:2016-07-17 14:15:03

标签: python numpy rounding number-formatting

我使用python和numpy发现了这种奇怪的行为:

print('%10.3f' %0.4975)

返回0.497,而

numpy.round(0.4975,3)

按预期返回0.498。 对于其他类似的数字,我总是得到print语句来提供正确的舍入值(例如:0.5975 - > 0.598)。 为什么是这样? 我在Windows 7上使用python 3.4和numpy 1.9.2。

1 个答案:

答案 0 :(得分:6)

在双精度中,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。实际上,在双精度中,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。