我使用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。
答案 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,......如何舍入的比较:
>>> [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]
>>> 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。