I am trying to put some numbers into numpy array
>>> np.array([20000001]).astype('float32')
array([ 20000000.], dtype=float32)
where did 1 go?
I am trying to put some numbers into numpy array
>>> np.array([20000001]).astype('float32')
array([ 20000000.], dtype=float32)
where did 1 go?
You simply don't have enough precision. The float32
has only approximately 7 digits of accuracy, whereas the float64
has approximately 16 digits of accuracy. Thus, any time you convert to a float32
, it's only guaranteed to be "correct" to within about a part in 10^7. So, for example, you can try this:
>>> np.array([20000001]).astype('float64')
array([ 20000001.])
That's the expected answer. (The dtype=float64
is automatically omitted, because that's the default.) In fact, you can go further and find
>>> np.array([2000000000000001]).astype('float64')[0]
2000000000000001.0
but
>>> np.array([20000000000000001]).astype('float64')[0]
20000000000000000.0
At some point, no matter how high your precision, you'll always get to the point where float
s drop the least significant digits. See here for more info on float
s.
On the other hand, python's int
objects have many more digits they can keep track of. In python 3, it's practically unlimited. So int
s have basically infinite precision. See here for more info on int
s.
with float32
you can't resolve it
>>> np.finfo(np.float32).eps
1.1920929e-07
eps
here gives you "the smallest representable positive number such that 1 + eps
!= 1" which is a measure for float32
accuracy. Multiply that with 20,000,000 and it's just too large.
Less informally, if one wants to avoid computing the binary representation of n then eps * n / base is a convenient lower bound for the resolution around n. While as @hobbs points out eps * n is an upper bound.
Also note that for example 1 + 0.6*eps may actually return something != 1, this is, however, due to rounding. Subtracting 1 from the result returns eps, not 0.6*eps.
First of all, float64
works in this case:
>>> np.array([20000001]).astype('float32')
array([ 20000000.], dtype=float32)
>>> np.array([20000001]).astype('float64')
array([ 20000001.])
How does a float
work under the hood:
What's the difference between float32
and float64
?:
With float32
, you get 23 bits to represent the digits plus 1 bit to represent the sign. Lets view 20000001
in binary:
0b 1 0011 0001 0010 1101 0000 0001 ---->
0b 1 0011 0001 0010 1101 0000 00
So the last two bits "01" will get cut off when converting from int
to float32
.
Interestingly, converting 20000003
will get you 20000004
:
>>> np.array([20000003]).astype('float32')
array([ 20000004.], dtype=float32)
And that is:
0b 1 0011 0001 0010 1101 0000 0011 ---->
0b 1 0011 0001 0010 1101 0000 01