Python float to ratio
Use the fractions
module to simplify fractions:
>>> from fractions import Fraction
>>> Fraction(3.2)
Fraction(3602879701896397, 1125899906842624)
>>> Fraction(3.2).limit_denominator()
Fraction(16, 5)
From the Fraction.limit_denominator()
function:
Finds and returns the closest
Fraction
toself
that has denominator at most max_denominator. This method is useful for finding rational approximations to a given floating-point number
Floating point numbers are limited in precision and cannot represent many numbers exactly; what you see is a rounded representation, but the real number is:
>>> format(3.2, '.50f')
'3.20000000000000017763568394002504646778106689453125'
because a floating point number is represented as a sum of binary fractions; 1/5 can only be represented by adding up 1/8 + 1/16 + 1/128 + more binary fractions for increasing exponents of two.
It's not 16/5 because 3.2
isn't 3.2 exactly... it's a floating point rough approximation of it... eg: 3.20000000000000017764
While using the fractions module, it is better to provide a string instead of a float to avoid floating point representation issues.
For example, if you pass '3.2'
instead of 3.2
you get your desired result:
In : fractions.Fraction('3.2')
Out: Fraction(16, 5)
If you already have the value stored in a variable, you can use string formatting as well.
In : value = 3.2
In : fractions.Fraction(f'{value:.2f}')
Out: Fraction(16, 5)