Question

  1. I have K a list of floats that comes from some previous calculation, such as:

    K = numpy.arange(0.01, 0.3, 0.01)
    K =  [0.01, .... 0.28999999999999998, 0.29999999999999999]
    
  2. Now, lets round those numbers to the 2nd decimal:

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

    Gives:

    >>> 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]
    

Now, if i was to manually input K as a list, simply writing each element:

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

and then do:

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

then the result is as expected:

>>> 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]

So there is a different treatment between the list that is provided by some calculation and the one that is simply input ? Why ?

Was it helpful?

Solution

This difference is due to the fact that in the first case the result contains np.float64s while when you enter the numbers directly you are using python's built-in float which has a smarter string representation:

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]

Now if we check the types of the elements of these lists:

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)

However the numbers represented are the same!

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

The printed value is different because python built-in floats are smarter and display the shorter literal that would represent the given floating-point number (see python's 3.1 What's new document and associated issue1580):

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

Numpy does do this and instead just outputs the "raw/actual floating-point number represented". But notice that the result is the same, it is only displayed differently, although in an equivalent way.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top