Comment convertir un nombre décimal en fraction?

Je me demandais comment convertir une décimale en une fraction dans sa forme la plus basse en Python.

Par exemple:

0.25  -> 1/4
0.5   -> 1/2
1.25  -> 5/4
3     -> 3/1
41
demandé sur nbro 2014-04-28 18:47:40

4 réponses

, Vous avez deux options:

  1. Utiliser float.as_integer_ratio():

    >>> (0.25).as_integer_ratio()
    (1, 4)
    

    (depuis Python 3.6, vous pouvez faire de même avec un objet decimal.Decimal() .)

  2. Utiliser le fractions.Fraction() type:

    >>> from fractions import Fraction
    >>> Fraction(0.25)
    Fraction(1, 4)
    

Ce dernier a une conversion str() très utile:

>>> str(Fraction(0.25))
'1/4'
>>> print Fraction(0.25)
1/4

Parce que les valeurs à virgule flottante peuvent être imprécises, vous pouvez vous retrouver avec des fractions "étranges"; limitez le dénominateur pour "simplifier" quelque peu la fraction, avec Fraction.limit_denominator():

>>> Fraction(0.185)
Fraction(3332663724254167, 18014398509481984)
>>> Fraction(0.185).limit_denominator()
Fraction(37, 200)

Si vous utilisez toujours python 2.6, alors Fraction() ne prend pas encore en charge le passage direct d'un float, mais vous pouvez combiner les deux techniques ci-dessus en:

Fraction(*0.25.as_integer_ratio())

, Ou vous pouvez simplement utiliser l'Fraction.from_float() méthode de la classe:

Fraction.from_float(0.25)

Qui fait essentiellement la même chose, par exemple prendre le tuple de rapport entier et le passer en tant que deux arguments distincts.

Et une petite démo avec vos valeurs d'échantillon:

>>> for f in (0.25, 0.5, 1.25, 3.0):
...     print f.as_integer_ratio()
...     print repr(Fraction(f)), Fraction(f)
... 
(1, 4)
Fraction(1, 4) 1/4
(1, 2)
Fraction(1, 2) 1/2
(5, 4)
Fraction(5, 4) 5/4
(3, 1)
Fraction(3, 1) 3

Les deux Le module fractions et la méthode float.as_integer_ratio() sont nouveaux dans Python 2.6.

76
répondu Martijn Pieters 2017-01-09 11:27:33
from fractions import Fraction

print(Fraction(0.25))
print(Fraction(0.5))
print(Fraction(1.25))
print(Fraction(3))

#1/4
#1/2
#5/4
#3
7
répondu ajkn1992 2014-04-28 14:49:21

Si vous souhaitez imprimer une fraction appropriée , Cette petite recette devrait faire:

from fractions import Fraction    

def dec_to_proper_frac(dec):
    sign = "-" if dec < 0 else ""
    frac = Fraction(abs(dec))
    return (f"{sign}{frac.numerator // frac.denominator} "
            f"{frac.numerator % frac.denominator}/{frac.denominator}")

Cela affichera comme suit:

>>> dec_to_proper_frac(3.75)
>>> "3 3/4"
2
répondu The Aelfinn 2018-03-15 21:19:00

Pour développer Martijn Pieters excellente réponse avec une option supplémentaire en raison de l'imprécision inhérente aux flotteurs plus complexes. Par exemple:

>>> f = 0.8857097
>>> f.as_integer_ratio()
(1994440937439217, 2251799813685248)          # mathematically wrong
>>> Fraction(f)
Fraction(1994440937439217, 2251799813685248)  # same result but in a class
>>> Fraction(f).limit_denominator()
Fraction(871913, 984423)                      # still imprecise

Le résultat mathématique souhaité était {[6] } qui peut être obtenu en lançant une chaîne et en la manipulant ensuite.

Réponse Modifiée

J'ai trouvé un moyen beaucoup plus simple de résoudre le problème de précision.

>>> Fraction(str(f))
Fraction(8857097, 10000000)

Le Casting d'une chaîne permet également une décimale précise les instances

>>> Decimal(f).as_integer_ratio()
(1994440937439217, 2251799813685248)
>>> Decimal(str(f)).as_integer_ratio()
(8857097, 10000000)

Réponse Originale

def float_to_ratio(flt):
    if int(flt) == flt:        # to prevent 3.0 -> 30/10
        return int(flt), 1
    flt_str = str(flt)
    flt_split = flt_str.split('.')
    numerator = int(''.join(flt_split))
    denominator = 10 ** len(flt_split[1])
    return numerator, denominator

Maintenant, nous allons le tester:

>>> float_to_ratio(f)
(8857097, 10000000)      # mathematically correct

Je noterai que ce type de précision de fraction n'est pas optimisé et ne sera généralement pas nécessaire, mais pour être complet, c'est ici. Cette fonction ne simplifie pas la fraction, mais vous pouvez faire un traitement supplémentaire pour la réduire:

>>> n = 0.5
>>> float_to_ratio(n)
(5, 10)
>>> Fraction(*float_to_ratio(n))
Fraction(1, 2)
1
répondu Matt Eding 2018-02-25 18:58:02