Is there a way to turn a decimal number into a fraction using python

im trying to make a calculator that is as advanced as i can make it, and i want to turn floats to fractions. Does any one know how to do that is possible

Simply use float.as_integer_ratio(). Example:

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

Note that because floats are only approximations of real numbers, you’re not getting exactly (1, 3) in the second example. For doing fraction arithmetic, see the fractions module in the standard library.

2 Likes

fractions.Fraction also has limit_denominator, which you can use to get a “simpler” rational approximation for a float:

>>> from fractions import Fraction
>>> Fraction(1/3)
Fraction(6004799503160661, 18014398509481984)
>>> Fraction(1/3).limit_denominator(1_000_000)
Fraction(1, 3)
2 Likes

Indeed. Do be aware, though, that this is NOT recreating the original ratio; it is finding the nearest fraction with a denominator within the limit. You can easily trick it into giving a quite wrong value. But that’s (probably) okay, since it’s in good company…

If the number is got from a user as a string, it’s probably better to convert it to Decimal and use its as_integer_ratio or just use it directly in calculations.

First you say “decimal number”, then you say “floats”. Which one is it? What do you actually have, exactly?

The fractions.Fraction class can process numeric strings (see the source for more information), e.g.:

>>> Fraction('1/3')
Fraction(1, 3)

>>> Fraction('1/3').as_integer_ratio()
(1, 3)

>>> Fraction('-3.245')
Fraction(-649, 200)

>>> Fraction('-3.245').as_integer_ratio()
(-649, 200)

In the implementation of fractions.Fraction it appears that for numeric string inputs the numerator and denominator are extracted from the leading digits and the fractional part via regex matching, which avoids Python integer division and the corresponding fractional representations with very large numerators and denominators.

It has been noted that Fraction.limit_denominator gives you a rational approximation to the given float by limiting the denominator of the fractional form of the approximation to a given magnitude. This is based on the principle of Diophantine approximation of real numbers by rational numbers, which links to continued fractions, specifically to the sequence of convergents (partial sums) of a continued fraction, which converge to the actual value of the given number - the larger the convergent the closer it is to the actual number.