舍入数字 - 这里有什么问题?

时间:2014-02-04 15:15:19

标签: python numpy python-3.3 rounding

  1. 我有一个来自之前计算的浮动列表,例如:

    K = numpy.arange(0.01, 0.3, 0.01)
    K =  [0.01, .... 0.28999999999999998, 0.29999999999999999]
    
  2. 现在,让这些数字绕过第二个小数:

    K_rounded_2  = [ round(kk, 2) for kk in K ]
    

    给予:

    >>> K_rounded_2
    [0.01, 0.02, 0.029999999999999999, 0.040000000000000001, 0.050000000000000003, 0.059999999999999998, 0.070000000000000007, 0.080000000000000002, 0.089999999999999997, 0.10000000000000001, 0.11, 0.12, 0.13, 0.14000000000000001, 0.14999999999999999, 0.16, 0.17000000000000001, 0.17999999999999999, 0.19, 0.20000000000000001, 0.20999999999999999, 0.22, 0.23000000000000001, 0.23999999999999999, 0.25, 0.26000000000000001, 0.27000000000000002, 0.28000000000000003, 0.28999999999999998, 0.29999999999999999]
    
  3. 现在,如果我手动输入K作为列表,只需编写每个元素:

    K = [ enter value 1, enter value 2, ...]
    

    然后执行:

    K_rounded_2  = [ round(kk, 2) for kk in K ]
    

    然后结果如预期:

    >>> K_rounded_2
    [0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3]
    

    因此,某些计算提供的列表与简单输入的列表之间存在不同的处理方式?为什么?

1 个答案:

答案 0 :(得分:3)

这种差异是由于在第一种情况下结果包含np.float64 s,而当您直接输入数字时,您使用的是python的内置float ,它更智能字符串表示

In [1]: import numpy as np

In [2]: a = np.arange(0.01, 0.3, 0.01)

In [3]: a
Out[3]: 
array([ 0.01,  0.02,  0.03,  0.04,  0.05,  0.06,  0.07,  0.08,  0.09,
        0.1 ,  0.11,  0.12,  0.13,  0.14,  0.15,  0.16,  0.17,  0.18,
        0.19,  0.2 ,  0.21,  0.22,  0.23,  0.24,  0.25,  0.26,  0.27,
        0.28,  0.29])

In [4]: [round(elem, 2) for elem in a]
Out[4]: 
[0.01,
 0.02,
 0.029999999999999999,
 0.040000000000000001,
 0.050000000000000003,
 0.059999999999999998,
 0.070000000000000007,
 0.080000000000000002,
 0.089999999999999997,
 0.10000000000000001,
 0.11,
 0.12,
 0.13,
 0.14000000000000001,
 0.14999999999999999,
 0.16,
 0.17000000000000001,
 0.17999999999999999,
 0.19,
 0.20000000000000001,
 0.20999999999999999,
 0.22,
 0.23000000000000001,
 0.23999999999999999,
 0.25,
 0.26000000000000001,
 0.27000000000000002,
 0.28000000000000003,
 0.28999999999999998]

In [5]: b = [0.01,
   ...:  0.02,
   ...:  0.029999999999999999,
   ...:  0.040000000000000001,
   ...:  0.050000000000000003,
   ...:  0.059999999999999998,
   ...:  0.070000000000000007,
   ...:  0.080000000000000002,
   ...:  0.089999999999999997,
   ...:  0.10000000000000001,
   ...:  0.11,
   ...:  0.12,
   ...:  0.13,
   ...:  0.14000000000000001,
   ...:  0.14999999999999999,
   ...:  0.16,
   ...:  0.17000000000000001,
   ...:  0.17999999999999999,
   ...:  0.19,
   ...:  0.20000000000000001,
   ...:  0.20999999999999999,
   ...:  0.22,
   ...:  0.23000000000000001,
   ...:  0.23999999999999999,
   ...:  0.25,
   ...:  0.26000000000000001,
   ...:  0.27000000000000002,
   ...:  0.28000000000000003,
   ...:  0.28999999999999998]

In [6]: [round(elem, 2) for elem in b]
Out[6]: 
[0.01,
 0.02,
 0.03,
 0.04,
 0.05,
 0.06,
 0.07,
 0.08,
 0.09,
 0.1,
 0.11,
 0.12,
 0.13,
 0.14,
 0.15,
 0.16,
 0.17,
 0.18,
 0.19,
 0.2,
 0.21,
 0.22,
 0.23,
 0.24,
 0.25,
 0.26,
 0.27,
 0.28,
 0.29]

现在,如果我们检查这些列表的元素类型:

In [10]: rounded_a = [round(elem, 2) for elem in a]
    ...: rounded_b = [round(elem, 2) for elem in b]
    ...: 

In [11]: type(rounded_a[0]), type(rounded_b[0])
Out[11]: (numpy.float64, builtins.float)

然而代表的数字是相同的!

In [12]: rounded_a[0] == rounded_b[0]
Out[12]: True
In [13]: rounded_a[-1] == rounded_b[-1]
Out[13]: True

打印的值是不同的,因为python内置浮点数更智能,并显示代表给定浮点数的较短字面值 (参见python的3.1 What's new文档和相关的issue1580):

In [15]: 0.28999999999999998
Out[15]: 0.29

Numpy会这样做而只是输出“原始/实际浮点数表示”。但请注意结果是相同的,它只是显示,但是以相同的方式。