Skip to content Skip to sidebar Skip to footer

Is There A Way To Return A Fully Reduced Ratio When Calling .as_integer_ratio()?

I noticed something strange when calling .as_integer_ratio() on some floats. for example: (2.2).as_integer_ratio() This will return a tuple: (2476979795053773, 1125899906842624) I

Solution 1:

Floating point can't actually represent most values as typed. 2.2 is a convenient shorthand for the closest value to 2.2, but 2.2 doesn't actually exist:

>>>print('{:.16f}'.format(2.2))
2.2000000000000002

If you want decimal accurate representations, you'll need to use the decimal module instead of float:

>>>from decimal import Decimal>>>Decimal('2.2').as_integer_ratio()  # Constructing from str is *mandatory* for proper precision
(11, 5)

Solution 2:

The answer by @ShadowRanger is correct. The value "2.2" is converted to the closest binary fraction. And .as_integer_ratio() returns that binary fraction. However, there are other nearby rational numbers that result in the same binary representation when converted to a float. It is possible to find a simpler fraction using a Stern-Brocot tree.

gmpy2 has an implementation of the Stern-Brocot algorithm and it is exposed as .as_simple_fraction().

>>> gmpy2.mpfr("2.2").as_integer_ratio()
(mpz(2476979795053773), mpz(1125899906842624))
>>> gmpy2.mpfr("2.2").as_simple_fraction()
mpq(11,5)

Post a Comment for "Is There A Way To Return A Fully Reduced Ratio When Calling .as_integer_ratio()?"