Подтвердить что ты не робот

Как преобразовать десятичное число во фракцию?

Мне было интересно, как преобразовать десятичную дробь в дробную часть в ее младшей форме в Python.

Например:

0.25  -> 1/4
0.5   -> 1/2
1.25  -> 5/4
3     -> 3/1
4b9b3361

Ответ 1

У вас есть два варианта:

Последний имеет очень полезное преобразование str():

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

Поскольку значения с плавающей запятой могут быть неточными, вы можете получить "странные" фракции; ограничьте знаменатель "немного упростить" фракцию, Fraction.limit_denominator():

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

Если вы все еще используете Python 2.6, то Fraction() пока не поддерживает передачу в float напрямую, но вы можете объединить эти два метода выше:

Fraction(*0.25.as_integer_ratio())

Или вы можете просто использовать метод Fraction.from_float():

Fraction.from_float(0.25)

который по существу делает то же самое, например. возьмите целочисленный кортеж отношения и передайте это как два отдельных аргумента.

И небольшая демонстрация с вашими выборками:

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

Оба модуля fractions и float.as_integer_ratio() являются новыми в Python 2.6.

Ответ 2

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

Ответ 3

Чтобы расширить Martijn Pieters отличный ответ с дополнительным вариантом из-за неточности, присущей более сложным поплавкам. Например:

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

Желаемый математический результат был 8857097/10000000, который может быть достигнут путем литья в строку и последующего манипулирования им.

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

Теперь давайте протестируем его:

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

Отмечу, что такая точность фракции не оптимизирована и, как правило, не нужна, но для полноты она здесь. Эта функция не упрощает фракцию, но вы можете выполнить дополнительную обработку, чтобы уменьшить ее:

>>> n = 0.5
>>> float_to_ratio(n)
(5, 10)
>>> Fraction(*float_to_ratio(n))
Fraction(1, 2)