web-dev-qa-db-fra.com

Comment convertir un nombre décimal en fraction?

Je me demandais comment convertir un nombre décimal 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
49
user2370460

Vous avez deux options:

  1. Utilisez float.as_integer_ratio() :

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

    (à partir de Python 3.6, vous pouvez faites de même avec un objet decimal.Decimal() _) .)

  2. Utilisez le type fractions.Fraction() _ :

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

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

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

Comme les valeurs en virgule flottante peuvent être imprécises, vous pouvez vous retrouver avec des fractions "étranges"; limite le dénominateur à '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 peut combiner les deux techniques ci-dessus en:

Fraction(*0.25.as_integer_ratio())

Ou vous pouvez simplement utiliser la méthode Fraction.from_float() class :

Fraction.from_float(0.25)

qui fait essentiellement la même chose, par ex. prenez le ratio entier Tuple et transmettez-le sous forme de deux arguments distincts.

Et une petite démo avec vos exemples de valeurs:

>>> 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

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

96
Martijn Pieters
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
9
ajknzhol

Si vous souhaitez imprimer un 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 va imprimer comme suit:

>>> dec_to_proper_frac(3.75)
>>> "3 3/4"
4
The Aelfinn

Pour développer Martijn Pieters excellente réponse avec une option supplémentaire en raison de l'imprécision inhérente à des 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 8857097/10000000 qui peut être obtenu en convertissant une chaîne puis en la manipulant.

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)

La conversion en chaîne permet également des instances Decimal précises

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

Réponse d'origine

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 testons-le:

>>> 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 il est ici complet. Cette fonction ne simplifie pas la fraction, mais vous pouvez effectuer 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)
4
Matt Eding