You can not represent 0.1 exactly in binary IEEE 754 format, which is what most modern architectures use internally to represent floating point numbers.
The closest binary value to 0.1 is just a shade under truth. When you add this nearest approximation five times, the error will increase.
According to the docs for np.arange
:
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.
The reason is that by clamping the ends, linapace
can make some assurances about the cumulative error which arange
can not. Each individual step used by linspace
may not be the closest binary representation of 0.1, but each element will be as close as possible to n * 0.1
from the start and end.
The linapace
call corresponding to np.arange(0.5, 1.1, 0.1)
is
np.linspace(0.5, 1.0, 6)
The other advantage of linspace
is that you fix the number of points. Also according to the arange
docs (the return value):
For floating point arguments, the length of the result is ceil((stop - start)/step)
. Because of floating point overflow, this rule may result in the last element of out being greater than stop.