1

While coding some array iteration stuff, I came across this strange behavior of the numpy arange() function :

>>> import numpy as np

>>> np.arange(0.13,0.16, step=0.01)
array([0.13, 0.14, 0.15])

>>> np.arange(0.12,0.16, step=0.01)
array([0.12, 0.13, 0.14, 0.15, 0.16])

>>> np.arange(0.11,0.16, step=0.01)
array([0.11, 0.12, 0.13, 0.14, 0.15])

As you can see, when asked to start on 0.13, the result stops one step short of the end value (as it should) but when asked to start on 0.12, the last value is returned ! Further down, starting on 0.11, the last value is gone again.

This causes some obvious problems if you're expecting the array to be increased by one when extending the range by exactly one step...

Any ideas on why the inconsistant behavior ?

System info : Python 3.6.5, numpy 1.14.0

RoB
  • 1,833
  • 11
  • 23
  • 1
    This issue has been reported in the past in several posts. A bit frustrating, I concur. The problem lies in floating point precision, and it is aknowledged in the `numpy.arange` docs (see also the answer below). The recommended approach is to use `np.linspace` or something like `np.arange(11,16)/100` – Tarifazo Jan 09 '19 at 14:07
  • Possible duplicate of [numpy \`arange\` exceeds end value?](https://stackoverflow.com/questions/35376101/numpy-arange-exceeds-end-value) – Pierre de Buyl Jan 09 '19 at 14:47
  • @PierredeBuyl Oh, Indeed ! I didn't quite know what to look for when I first searched the site. – RoB Jan 10 '19 at 06:38

1 Answers1

4

np.arange documentation states:

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.

So, you should consider using np.linspace instead.

You can implement your own arange method using linspace:

def my_arange(start, end, step):
    return np.linspace(start, end, num=round((end-start)/step), endpoint=False)

And it would work as expected:

In [27]: my_arange(0.13, 0.16, step=0.01)
Out[27]: array([ 0.13,  0.14,  0.15])

In [28]: my_arange(0.12, 0.16, step=0.01)
Out[28]: array([ 0.12,  0.13,  0.14,  0.15])

In [29]: my_arange(0.11, 0.16, step=0.01)
Out[29]: array([ 0.11,  0.12,  0.13,  0.14,  0.15])
Ahmad Khan
  • 2,655
  • 19
  • 25