python numpy arange unexpected results

Solution 1:

I'm guessing that you're seeing the effects of floating point rounding.

numpy.arange does the same thing as python's range: It doesn't include the "endpoint". (e.g. range(0, 4, 2) will yield [0,2] instead of [0,2,4])

However, for floating point steps, the rounding errors are accumulate, and occasionally the last value will actually include the endpoint.

As noted in the documentation for arange:

When using a non-integer step, such as 0.1, the results will often not be consistent. It is better to use linspace for these cases.

numpy.linspace generates a specified number of points between a starting and ending point. Incidentally, it does include the endpoints by default.

Solution 2:

Perhaps it has to do with limitations on floating point numbers. Due to machine precision, it is not possible to store every conceivable value perfectly as a floating point. For example:

>>> 8.4
8.4000000000000004
>>> 8.35
8.3499999999999996

So, 8.4 as a floating point is slightly greater than the actual value of 8.4, while 8.35 as a floating point is a tiny bit less.

Solution 3:

the help of arange function says

    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`.

for python 2.7, Conversions between floating-point numbers and strings are now correctly rounded on most platforms.

in 2.7

>>> float(repr(2.3))
2.3

in 2.6

>>> float(repr(2.3))
2.2999999999999998

Solution 4:

I had the same problem and I implemented my own function to correct for this rounding issue with numpy.arange :

import numpy as np
def my_arange(a, b, dr, decimals=6):
    res = [a]
    k = 1
    while res[-1] < b:
        tmp = round(a + k*dr,decimals)
        if tmp > b:
            break   
        res.append(tmp)
        k+=1

    return np.asarray(res)