Why does numpy convert 20000001 int to float32 as 20000000.?

I'm trying to put some numbers in a numpy array

>>> np.array([20000001]).astype('float32') array([ 20000000.], dtype=float32) 

where was 1 go?

+5
source share
3 answers

You just don't have enough accuracy. float32 has only about 7 digits of precision, while float64 has about 16 digits of precision. Thus, whenever you convert to float32 , it is only guaranteed to be "correct" with an accuracy of 10 ^ 7. So, for example, you can try the following:

 >>> np.array([20000001]).astype('float64') array([ 20000001.]) 

This is the expected answer. ( dtype=float64 automatically omitted because this is the default value.) In fact, you can go ahead 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 accuracy, you always get to the point where the least significant numbers are dropped by the float . See here for more information on float s.

On the other hand, python int objects have a lot more digits that they can track. In python 3 it is almost unlimited. So int has basically infinite precision. See here for more information on int s.

+7
source

with float32 you cannot solve 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 of the precision of float32 . Multiply this by 20,000,000 and it is too large.

Less informally, if you want to avoid computing the binary representation of n, then eps * n / base is a convenient lower bound for resolution around n. While @hobbs indicates that eps * n is the upper bound.

Also note that, for example, 1 + 0.6 * eps may actually return something! = 1, however this is due to rounding. Subtracting 1 from the result returns eps, not 0.6 * eps.

+2
source

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 float works under the hood:

enter image description here


What is the difference between float32 and float64 ?:

  • 32bit (single precision float): 24-bit significance
  • 64-bit (double precision float): 53 bits.


With float32 you get 23 bits to represent digits plus 1 bit to represent a character. Allows you to view 20000001 in binary format:

 0b 1 0011 0001 0010 1101 0000 0001 ----> 0b 1 0011 0001 0010 1101 0000 00 

Thus, the last two bits of “01” will be disabled when converting from int to float32 .

Interestingly, converting 20000003 will lead you to 20000004 :

 >>> np.array([20000003]).astype('float32') array([ 20000004.], dtype=float32) 

And this:

 0b 1 0011 0001 0010 1101 0000 0011 ----> 0b 1 0011 0001 0010 1101 0000 01 
+2
source

Source: https://habr.com/ru/post/1264252/


All Articles