Ich habe mich gefragt, wie man in Python eine Dezimalstelle in einen Bruch in ihrer niedrigsten Form konvertiert.
Zum Beispiel:
0.25 -> 1/4
0.5 -> 1/2
1.25 -> 5/4
3 -> 3/1
Ich habe mich gefragt, wie man in Python eine Dezimalstelle in einen Bruch in ihrer niedrigsten Form konvertiert.
Zum Beispiel:
0.25 -> 1/4
0.5 -> 1/2
1.25 -> 5/4
3 -> 3/1
Antworten:
Sie haben zwei Möglichkeiten:
Verwendung float.as_integer_ratio()
:
>>> (0.25).as_integer_ratio()
(1, 4)
(Ab Python 3.6 können Sie dasselbe mit einem decimal.Decimal()
Objekt tun .)
Verwenden Sie den fractions.Fraction()
Typ :
>>> from fractions import Fraction
>>> Fraction(0.25)
Fraction(1, 4)
Letzteres hat eine sehr hilfreiche str()
Konvertierung:
>>> str(Fraction(0.25))
'1/4'
>>> print Fraction(0.25)
1/4
Da Gleitkommawerte ungenau sein können, kann es zu "seltsamen" Brüchen kommen. Begrenzen Sie den Nenner, um den Bruch etwas zu vereinfachen, mit Fraction.limit_denominator()
:
>>> Fraction(0.185)
Fraction(3332663724254167, 18014398509481984)
>>> Fraction(0.185).limit_denominator()
Fraction(37, 200)
Wenn Sie Python 2.6 noch verwenden, wird Fraction()
die float
direkte Übergabe von a noch nicht unterstützt. Sie können jedoch die beiden oben genannten Techniken kombinieren, um:
Fraction(*0.25.as_integer_ratio())
Oder Sie können einfach die Fraction.from_float()
Klassenmethode verwenden :
Fraction.from_float(0.25)
Dies macht im Wesentlichen dasselbe, z. B. nehmen Sie das Ganzzahlverhältnis-Tupel und übergeben Sie es als zwei separate Argumente.
Und eine kleine Demo mit Ihren Beispielwerten:
>>> 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
Sowohl das fractions
Modul als auch die float.as_integer_ratio()
Methode sind neu in Python 2.6.
Fraction(*(0.25).as_integer_ratio())
stattdessen in diesem Fall.
fractions
Modul float.as_integer_ratio
als auch in Python 2.6 hinzugefügt wurden. Wenn Sie eine ältere Version von Python ausführen, sind diese nicht verfügbar.
Fraction.from_float()
Klassenmethode zu verpassen , viel klarer. Fraction.from_float(0.25)
.
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
Fraction(.2)
wird Fraction(3602879701896397, 18014398509481984)
. Es könnte besser sein, den Konstruktor mit zwei Argumenten zu verwenden, z. Fraction(2,10)
Martijn Pieters ausgezeichnete Antwort mit einer zusätzlichen Option aufgrund der Ungenauigkeit, die komplexeren Schwimmern innewohnt, zu erweitern. Zum Beispiel:
>>> 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
Das gewünschte mathematische Ergebnis war 8857097/10000000
das, das erreicht werden kann, indem eine Saite gegossen und dann manipuliert wird.
Bearbeitete Antwort
Ich habe einen viel einfacheren Weg gefunden, um das Genauigkeitsproblem zu lösen.
>>> Fraction(str(f))
Fraction(8857097, 10000000)
Das Umwandeln einer Zeichenfolge ermöglicht auch genaue Dezimalinstanzen
>>> Decimal(f).as_integer_ratio()
(1994440937439217, 2251799813685248)
>>> Decimal(str(f)).as_integer_ratio()
(8857097, 10000000)
Ursprüngliche Antwort
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
Jetzt testen wir es:
>>> float_to_ratio(f)
(8857097, 10000000) # mathematically correct
Ich werde bemerken, dass diese Art der Bruchgenauigkeit nicht optimiert ist und normalerweise nicht benötigt wird, aber der Vollständigkeit halber ist sie hier. Diese Funktion vereinfacht den Bruch nicht, aber Sie können zusätzliche Verarbeitung durchführen, um ihn zu reduzieren:
>>> n = 0.5
>>> float_to_ratio(n)
(5, 10)
>>> Fraction(*float_to_ratio(n))
Fraction(1, 2)
Wenn Sie einen richtigen Bruch drucken möchten , sollte dieses kleine Rezept Folgendes tun:
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}")
Dies wird wie folgt gedruckt:
>>> dec_to_proper_frac(3.75)
>>> "3 3/4"