J'écris un programme qui utilise le module Fractions
. Je veux obtenir la fraction la plus simplifiée d'un flotteur. Quand je l'essaye avec des nombres comme 0.5
, cela fonctionne correctement:
>>> str(fractions.Fraction(0.1)) '3602879701896397/36028797018963968' >>> str(fractions.Fraction(0.55)) '2476979795053773/4503599627370496'
Mais quand je l'essaye avec 0.55
ou 0.1
il affiche des fractions avec un numérateur et un dénominateur très élevés, au lieu de 11/20
et 1/10
.
>>> import fractions >>> str(fractions.Fraction(0.5)) '1/2'
Que puis-je faire pour être sûr que le script affichera toujours la fraction la plus simplifiée? Y a-t-il un moyen de le faire avec le module Fractions
ou un autre module, ou je dois écrire la fonction moi-même?
4 Réponses :
Essayez ceci:
In [77]: str(fractions.Fraction(0.55).limit_denominator()) Out[77]: '11/20' In [78]: str(fractions.Fraction(0.1).limit_denominator()) Out[78]: '1/10'
Voir les résultats:
fractions.Fraction(0.1).limit_denominator()
Lorsque vous passez 0.55
, vous passez un float, donc c'est déjà une représentation inexacte avant que la Fraction
ne reçoive la valeur.
Alternativement, si vous passez une chaîne à la place, vous pouvez obtenir la valeur exacte que vous voulez:
>>> fractions.Fraction('0.55') Fraction(11, 20)
Essayez avec l'exemple de module decimal
de docs :
>>> from fractions import Fraction >>> from decimal import Decimal >>> Fraction(Decimal('0.55')) >>> Fraction(11, 20) >>> str(Fraction(11, 20)) >>> '11/20'
Passez-le sous forme de chaîne pour obtenir la fraction simplifiée:
>>> fractions.Fraction('0.1') Fraction(1, 10) >>> str(fractions.Fraction('0.1')) '1/10'
Lorsque vous passez
0.55
, vous passez un flottant, donc c'est déjà une représentation inexacte avant que laFraction
ne reçoive la valeurLe point crucial est que de simples fractions décimales comme par ex. 0,1 sont souvent des fractions périodiques dans le système dual. Les nombres à virgule flottante utilisés dans l'ordinateur aggravent encore la situation. Lecture recommandée: Guide en virgule flottante .
Si vous passez une chaîne comme
Fraction ('0.1')
cela fonctionnera.@khelwood Savez-vous ce qui fait apparaître les nombres géants pour
0.1
? Existe-t-il une règle déterministe pour cela?@roganjosh Seulement que le flotteur essaiera de stocker la valeur la plus proche de 0,1 qui correspond à sa représentation binaire.
Ok, donc je vais passer le nombre sous forme de chaîne. Cela résout le problème
Il ne s'agit pas simplement de stackoverflow.com/questions/23344185/… . Cela n'explique pas pourquoi je dois passer le nombre sous forme de chaîne.