Python Numpy Arange Unexpected Results

python numpy arange unexpected results

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.

Python numpy unexpected results in arange and linspace

In the Python console you will see

>>> 0.29/0.01
28.999999999999996
>>> import numpy as np
>>> np.int32(0.29/0.01)
28

So you are on the right path. This is due to floating point calculation. As soon as you cast it to np.int32, the decimal places will be truncated and the result is 28. Instead of just casting, you should round the result:

>>> np.int32(np.round(0.29/0.01))
29

For your application that means you have to write

lattice = np.asarray(np.round(lattice/cell_size),dtype=np.int32) ###This is supposed to contain matrix indices.

python numpy arange: strange behavior

Because of floating point error, 1.1, 0.01 and 0.12 are not as precise as one might expect, nor are mathematical operations between them. For example:

>>> 1.1 + 0.01 + 0.01 + 0.01
1.1300000000000001

See also:

>>> decimal.Decimal(0.1)
Decimal('0.1000000000000000055511151231257827021181583404541015625')
>>> decimal.Decimal(1.12)
Decimal('1.12000000000000010658141036401502788066864013671875')

If they were precise, np.arange(1.1, 1.12, 0.01) would be array([1.1 , 1.11])

np.arange specification mentions that as well: For the stop argument it writes:

stop : number

End of interval. The interval does not include this value, except in
some cases where step is not an integer and floating point round-off
affects the length of out.

You can avoid the problem by always specifying an upper limit which is between two steps, rather than exactly on the boundary:

>>> np.arange(1.1, 1.115, 0.01)
array([1.1 , 1.11])
>>> np.arange(1.1, 1.125, 0.01)
array([1.1 , 1.11, 1.12])
>>> np.arange(1.1, 1.135, 0.01)
array([1.1 , 1.11, 1.12, 1.13])

Unexpected output for numpy.arange with step size of 0.005

linspace might be better suited to your needs

In [401]: np.linspace(2.23, 2.24,3)
Out[401]: array([ 2.23 , 2.235, 2.24 ])

You specify the number of steps, rather than the interval. It has additional parameters to control details like the inclusion, or not, of the end point.

In [415]: np.linspace(2.23, 2.24,2,endpoint=False)
Out[415]: array([ 2.23 , 2.235])

python numpy arange unexpected results

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.

Is Numpy giving unexpected results?

Take np.random.choice(np.arange(0,X.shape[0]), size = train_size, replace = False)

The problem is, that np.random.randint will not be injectiv, basically the number 1 might apear twice. This means that index 1 will be set to True twice, while another one will not be set to True.

The np.random.choice function ensures, that every number will occur at most once (if you set replace = False

numpy.arange makes no sense at all. How does it work?

It's floating point precision, e.g. see this question: python numpy arange unexpected results

You could get around it like so:

>>> np.arange(14.04, 14.839, 0.08)
array([ 14.04, 14.12, 14.2, 14.28, 14.36, 14.44, 14.52, 14.6, 14.68, 14.76])

...but this is pretty hacky. It's usually a better idea to use numpy.linspace(), but then you have to give the number of steps, not the interval, so it can be a bit of a pain.

>>> np.linspace(14.04, 14.76, 9)
array([ 14.04, 14.13, 14.22, 14.31, 14.4, 14.49, 14.58, 14.67, 14.76])

Choose your poison!



Related Topics



Leave a reply



Submit