Skip to content

numpy.arange miscounts when step is large relative to value past stop #6238

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
kawochen opened this issue Aug 23, 2015 · 5 comments
Closed

Comments

@kawochen
Copy link
Contributor

 In [14]: len(numpy.arange(0, 10000000000000001, 100000000000000))
Out[14]: 101

In [15]: len(numpy.arange(0, 100000000000000000001, 1000000000000000000))
Out[15]: 100
@jaimefrio
Copy link
Member

To calculate the number of items, a rounded up division of (stop - start) / step is performed. This is done in floating point, and the loss of precision is what caused your missing last entry. If all three values are integers, we could alternatively take advantage of Python's arbitrary precision integers and use the (stop - start - 1) // step + 1 rounded up integer division formula, which should fix your problem.

@kawochen
Copy link
Contributor Author

Thanks. I suspected it was some kind of floating point arithmetic at work as well, but couldn't find the source code for that function. Can you point me to it? The doc says when all three are integers it does the same thing as the built-in range, but in this case it's different.

@jaimefrio
Copy link
Member

It's written in C. The function that ultimately creates the arange array is PyArray_ArangeObj, but the length is calculated by the auxiliary function _calc_length called by it.

@julianeagu
Copy link

I am getting a (similar?) bug:

For example, I get an extra number in this case:

x = np.arange(0.75,0.8,0.01) 
print x
[ 0.75  0.76  0.77  0.78  0.79  0.8 ]

but this works fine:

x = np.arange(0.75,1.0,0.01)
print x
[ 0.75  0.76  0.77  0.78  0.79  0.8   0.81  0.82  0.83  0.84  0.85  0.86 0.87  
0.88  0.89  0.9   0.91  0.92  0.93  0.94  0.95  0.96  0.97  0.98 0.99]

I'm using numpy version 1.11.2.

@charris
Copy link
Member

charris commented Nov 30, 2016

The problem is that .8 and .01 are not exactly representable in floating point, so the actual numbers used are not what they look like. For instance

 In [2]: print "%25.20f" % .8
   0.80000000000000004441

The way to do this sort of thing is to use linspace or integers and divide

In [1]: linspace(.75, .8, 5, endpoint=False)
Out[1]: array([ 0.75,  0.76,  0.77,  0.78,  0.79])

In [2]: arange(75, 80)/100.
Out[2]: array([ 0.75,  0.76,  0.77,  0.78,  0.79])

@charris charris closed this as completed Nov 30, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants