2016-02-19 88 views
0

为什么以下四舍五入不是在Python 3个工作,但只有在Python 2?Python 3中的四舍五入问题

random_nums = np.array([-1, 0, 1, 2, 3]) 
probabilities = np.array([0.01, 0.3, 0.58, 0.1, 0.01]) 
target = dict(zip(random_nums, probabilities)) 
target = {k: round(v, 2) for k, v in target.items()} 

out: 
{-1: 0.01, 
0: 0.29999999999999999, 
1: 0.57999999999999996, 
2: 0.10000000000000001, 
3: 0.01} 
+0

如果您需要确切的花车/双打舍入,转换为字符串输出时做四舍五入。由于显示的位数,这与所选浮点精度到达这些数字的距离相近。 –

回答

3

你跟NumPy的工作的Python float对象float64对象,而不是。这有几个后果:

  1. 在Python 3中,float64对象是使用与NumPy的舍入代码,而不是Python的四舍五入。对于float,Python的舍入代码总是给出正确舍入的结果。 NumPy的舍入代码没有。 (在Python 2中,这是不可能来覆盖自定义类型的round操作,所以当你圆一个float64对象在Python 2首先被转换为Python float,然后Python的舍入代码是用来给一个float的结果。这是,你看到上面的原因)

  2. 再次上的Python 3的Python 2和Python 3之间的差别,主要的原因,roundfloat64给出float64结果。在Python 2中,round一个float64对象上给出了一个float结果。

  3. Python float对象有不同的repr,这会给出较愉快的输出。特别是,Python的浮动repr保证双向传递用于(不太大,不能太小)的十进制值与至多15个显著数字:的0.58表示是'0.58',例如。 NumPy的float64对象的表示没有这个属性:它只是打印出基于存储的价值的最显著17个十进制数字的结果。

所以,如果你在一轮之前float对象转换你的价值观到Python,你会看到更开心输出(在某些情况下,结果可能会更一点点准确)。但请注意,仅仅因为输出看起来不错,这并不意味着你得到的结果是确切的。这一切都不改变的事实,0.58精确表示作为一个Python float(或实际上NumPy的float64,它使用相同的格式)。记住,用二进制浮点数,你看到的不是你得到的。

关于Python 3部分输出例如:

>>> random_nums = np.array([-1, 0, 1, 2, 3]) 
>>> probabilities = np.array([0.01, 0.3, 0.58, 0.1, 0.01]) 
>>> target = dict(zip(random_nums, probabilities)) 
>>> {k: round(v, 2) for k, v in target.items()} 
{0: 0.29999999999999999, 1: 0.57999999999999996, 2: 0.10000000000000001, 3: 0.01, -1: 0.01} 
>>> {k: round(float(v), 2) for k, v in target.items()} 
{0: 0.3, 1: 0.58, 2: 0.1, 3: 0.01, -1: 0.01} 
0

似乎工作正常。请记住,round返回一个浮点数。

它四舍五入到两位小数,但浮子固有inprecise(对于几乎所有的数),因此输出。

+0

解决此问题的最佳方法是什么? – Nickpick

+0

......解决什么问题? –

+0

所以输出看起来不错,如果你想的浮点输出,那么这就是你能做的最好的只有2位小数 – Nickpick