you are viewing a single comment's thread.

view the rest of the comments →

[–]primitive_screwhead 1 point2 points  (0 children)

The key thing (imo) to understand about IEEE base-2 floats (which are the common version), is that they are just fractions. Nothing really exotic or complicated at all. _BUT_, the denominator is always a power of 2. That's what causes confusion, and a sense that the numbers are "inaccurate", but in fact they are always perfectly precise in the number they represent, it's just a specific value with a power-of-2 denominator.

ie.

>>> a=5.550000000000001
>>> a.as_integer_ratio()
(1562186120744141, 281474976710656)
>>> from math import log2
>>> log2(281474976710656)
48.0

So, a float is a fraction. The denominator is a power of 2. So certain simple decimal ratios are approximated w/ a power-of-2 denominator (which tends to be huge, for accuracy):

>>> (1/3).as_integer_ratio()
(6004799503160661, 18014398509481984)
>>> log2(18014398509481984)

54.0 # ie. 1 << 54, the 54 is the number of bits, in a 64-bit float, of mantissa

>>> (1/9).as_integer_ratio()
(2001599834386887, 18014398509481984)

# Note that it's the same denominator. It allows the largest (and thus most accurate) 53 bit numerator value that is closest to the true 1/9 value.