Mi chiedevo come convertire un decimale in una frazione nella sua forma più bassa in Python.Come convertire un numero decimale in una frazione?
Ad esempio:
0.25 -> 1/4
0.5 -> 1/2
1.25 -> 5/4
3 -> 3/1
Mi chiedevo come convertire un decimale in una frazione nella sua forma più bassa in Python.Come convertire un numero decimale in una frazione?
Ad esempio:
0.25 -> 1/4
0.5 -> 1/2
1.25 -> 5/4
3 -> 3/1
Sono disponibili due opzioni:
Utilizzare float.as_integer_ratio()
: (., Come di Python 3.6, è possibile do the same with a decimal.Decimal()
object)
>>> (0.25).as_integer_ratio()
(1, 4)
Utilizzare la fractions.Fraction()
type:
>>> from fractions import Fraction
>>> Fraction(0.25)
Fraction(1, 4)
Quest'ultimo ha una molto utile str()
conversione:
>>> str(Fraction(0.25))
'1/4'
>>> print Fraction(0.25)
1/4
Poiché i valori in virgola mobile può essere impreciso, si può finire con 'strano 'frazioni; limitare il denominatore a 'semplificare' la frazione in qualche modo, con Fraction.limit_denominator()
:
>>> Fraction(0.185)
Fraction(3332663724254167, 18014398509481984)
>>> Fraction(0.185).limit_denominator()
Fraction(37, 200)
Se si sta utilizzando Python 2.6 ancora, quindi Fraction()
non ancora supporta il passaggio in un float
direttamente, ma si può combinare le due cose tecniche di cui sopra in:
Fraction(*0.25.as_integer_ratio())
Oppure si può semplicemente utilizzare il Fraction.from_float()
class method:
Fraction.from_float(0.25)
che essenzialmente fa la stessa cosa, ad es. prendere la tupla del rapporto intero e passarla come due argomenti separati.
E una piccola demo con i propri valori di esempio:
>>> 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
Sia il modulo fractions
e il metodo float.as_integer_ratio()
sono nuovi in Python 2.6.
Grazie! Le opzioni 1 funzionano, ma l'opzione 2 (Fraction (0.25)) mi dà l'errore: "TypeError: l'oggetto 'float' non può essere interpretato come un indice". Puoi dirmi perché? – user2370460
Ottima risposta. Link ed esempi molto utili. – fr1tz
@ user2370460: Quale versione di Python stai usando? –
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
Grazie, ma questo mi dà: "TypeError: l'oggetto 'float' non può essere interpretato come un indice". Puoi dirmi perché? – user2370460
Un buon suggerimento, ma vorrei aggiungere: il costruttore di un argomento funziona bene per alcuni numeri, ma non per altri. Ad esempio, 'Fraction (.2)' diventa 'Fraction (3602879701896397, 18014398509481984)'. Potrebbe essere meglio usare il costruttore a due argomenti, es. 'Frazione (2,10)' – Kevin
@Kevin: questo perché .2 non può essere rappresentato con precisione da un float. Vedi la mia risposta per una soluzione alternativa; limita il denominatore e puoi riportarlo a 2/10 in un batter d'occhio. –
Espandere la risposta eccellente di Martijn Pieters con un'opzione aggiuntiva a causa dell'imprecisione intrinseca con i galleggianti più complessi. Ad esempio:
>>> 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
Il risultato desiderato è stato matematico 8857097/10000000
che può essere realizzato per fusione in una stringa e poi manipolarlo.
A cura di risposta
ho trovato un modo molto più semplice per risolvere il problema precisione.
>>> Fraction(str(f))
Fraction(8857097, 10000000)
Casting da una stringa consente inoltre di precisare le istanze decimali
>>> Decimal(f).as_integer_ratio()
(1994440937439217, 2251799813685248)
>>> Decimal(str(f)).as_integer_ratio()
(8857097, 10000000)
risposta 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
Ora cerchiamo di testarlo:
>>> float_to_ratio(f)
(8857097, 10000000) # mathematically correct
Noterò che questo tipo di precisione della frazione non è ottimizzato e di solito non sarà necessario, ma per completezza è qui. Questa funzione non semplifica la frazione, ma è possibile eseguire un'ulteriore elaborazione per ridurla:
>>> n = 0.5
>>> float_to_ratio(n)
(5, 10)
>>> Fraction(*float_to_ratio(n))
Fraction(1, 2)
Convertire da 0,25 a 25/100, quindi calcolare il più grande fattore comune? –