Reputation: 3154
It seems numpy
is losing precision on numpy.int64 values when converted to float types.
My numpy version is 1.15.4 which seemed to fix this error.
Here is an example:
>>> value = 734625324872288246
>>> value_plus_1 = 734625324872288246 + 1
>>> items = [value, value_plus_1]
>>> value.bit_length()
60
>>> value_plus_1.bit_length()
60
>>> import numpy as np
>>> a = np.array(items, dtype = np.float128) # larger than needed for value
>>> a
array([7.34625325e+17, 7.34625325e+17], dtype=float128)
>>> a.astype(np.int64) # larger than needed for value
array([734625324872288256, 734625324872288256])
>>> np.__version__
'1.15.4'
As you can see, now both values in the array are equivalent, which shows a loss in precision that I am assuming happens on casting to float.
My question is; Is there something I am doing wrong when creating numpy arrays that can be rectified to not lose precision?
Upvotes: 1
Views: 1640
Reputation: 114811
(The question is almost certainly a duplicate, but my search-fu is weak today.)
There are only finitely many numbers that can be represented with 64 bit floating point numbers. The spacing between the numbers that are exactly representable depends on the magnitude of the numbers; you can find the spacing with the function numpy.spacing(x)
for a floating point number x
. In your case, the spacing of the floating point numbers around 734625324872288246 is 128:
In [33]: x = float(734625324872288246)
In [34]: x
Out[34]: 7.346253248722883e+17
In [35]: np.spacing(x)
Out[35]: 128.0
The integer value 734625324872288246 is not representable exactly as floating point. You can see that by casting the float back to integer; you don't get the same value:
In [36]: int(x)
Out[36]: 734625324872288256
You can represent 734625324872288256 exactly as a floating point number, but the next lower representable integer is 734625324872288256 - 128 = 734625324872288128.
And here are the obligatory links for questions about floating point:
Upvotes: 1
Reputation: 1116
The numpy documentation (https://docs.scipy.org/doc/numpy-1.15.0/user/basics.types.html) states that the implementation of float64 only uses 52 bits for the mantissa, and 11 bits for the exponent. This is most likely not enough accuracy to store your 60-bit numbers with full precision.
Upvotes: 3