Python 格式化数值和舍入值之间的差异
我使用python和numpy发现了这种奇怪的行为:Python 格式化数值和舍入值之间的差异,python,numpy,rounding,number-formatting,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。在双精度中,0.4975是8962163258467287/18014398509481984,比实数0
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.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
努比
这里的NumPy输出是人们在不考虑二进制表示的情况下所期望的
然而,
np.around([(2*i+1)/200表示范围(100)],2)
表明NumPy的算法也不总是符合预期:有两个数字(0.55和0.57)结尾有一个奇数。问题是,例如,0.545*100并不完全是109/2;相反,它是7670193115365377/140737488355328。在双精度中,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
努比
这里的NumPy输出是人们在不考虑二进制表示的情况下所期望的
然而,
np.around([(2*i+1)/200表示范围(100)],2)
表明NumPy的算法也不总是符合预期:有两个数字(0.55和0.57)结尾有一个奇数。问题是,例如,0.545*100并不完全是109/2;相反,它是7670193115365377/140737488355328。它应该与python和Numpy中浮点的二进制表示有关。请注意,0.4975-.497
会导致0.000500000000000004
,这不等于0.0005
。此外,请查看此链接中“轮”下的注释,感谢@Dietrich和Dan Patterson。这确实与浮点数的表示方式有关。奇怪但真实。这应该与python和Numpy中浮点数的二进制表示有关。请注意,0.4975-.497
会导致0.000500000000000004
,这不等于0.0005
。此外,请查看此链接中“轮”下的注释,感谢@Dietrich和Dan Patterson。这确实与浮点数的表示方式有关。奇怪但真实。
>>> [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. ])