By the conversion via .tolist()
you're not gaining or loosing any precision. You're just converting to another data type which chooses to represent itself differently. You seem to be thinking that by the conversion it turns the 0.8
into 0.7999999999999999
, but the situation is, it has never been 0.8
. This is due to limited floating point precision. You can verify yourself:
>>> import numpy
>>> a = numpy.arange(0.5, 1.5, 0.1, dtype=numpy.float64)
>>> a
array([0.5, 0.6, 0.7, 0.8, 0.9, 1. , 1.1, 1.2, 1.3, 1.4])
>>> a[3]
0.7999999999999999
The situation is that that every type can decide how its instances are represented via __repr__
or __str__
. In this specific case np.ndarray
decides to show a rounded version of its elements for more clarity. This can be controlled via numpy.set_printoptions
. This function only affects how arrays are displayed:
>>> numpy.set_printoptions(floatmode='unique')
>>> a
array([0.5 , 0.6 , 0.7 ,
0.7999999999999999, 0.8999999999999999, 0.9999999999999999,
1.0999999999999999, 1.1999999999999997, 1.2999999999999998,
1.4 ])
A note on np.arange
from the docs:
When using a non-integer step, such as 0.1, the results will often not be consistent. It is better to use numpy.linspace
for these cases.
Here are the results for linspace
:
>>> np.linspace(0.5, 1.5, 11)
array([0.5 , 0.6 , 0.7 ,
0.8 , 0.9 , 1. ,
1.1 , 1.2000000000000002, 1.3 ,
1.4 , 1.5 ])