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

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

我使用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.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. ])