Есть ли чистая реализация Python fractions.Fraction
это поддерживает long
s как числитель и знаменатель? К сожалению, возведение в степень, кажется, кодируется в возвратить плавание (ack!!!), который должен, по крайней мере, поддерживать использование decimal.Decimal
.
Если нет, я предполагаю, что могу, вероятно, сделать копию библиотеки и попытки заменить случаи float()
с чем-то соответствующим от Decimal
но я быть бы что-то, что это было протестировано другими прежде.
Вот пример кода:
base = Fraction.from_decimal(Decimal(1).exp())
a = Fraction(69885L, 53L)
x = Fraction(9L, 10L)
print base**(-a*x), type(base**(-a*x))
результаты в 0.0 <type 'float'>
где ответ должен быть действительно маленьким десятичным числом.
Обновление: у меня есть следующее обходное решение на данный момент (принятие, для ** b, это оба - части; конечно, мне будет нужна другая функция, когда exp_ будет плаванием или будет самостоятельно Десятичным числом):
def fracpow(base, exp_):
base = Decimal(base.numerator)/Decimal(base.denominator)
exp_ = Decimal(exp_.numerator)/Decimal(exp_.denominator)
return base**exp_
который дает ответ 4.08569925773896097019795484811E-516.
Мне все еще было бы интересно, если существует лучший способ сделать это без дополнительных функций (я предполагаю, работаю ли я с Fraction
класс достаточно, я найду другие плавания, прокладывающие себе путь в мои результаты).
«Поднять в степень» не является замкнутой операцией над рационалями (иначе, чем обычные четыре арифметические операции): нет рационального числа r
такого, что r = = 2 * * 0,5
. Легенда гласит, что Пифагор (из теоремы которого этот факт так просто следует) убил своего ученика Гиппаса за ужасное преступление доказать это; похоже, вы сочувствуете предполагаемой реакции Пифагора; -), учитывая ваше странное использование «должен».
Фракции Пайтона должны быть точными, поэтому неизбежно имеют место случаи, когда возведение фракции в степень другой фракции будет абсолютно неспособным вернуть фракцию в ее результате; и «должен» просто не может быть разумно применен к математической невозможности.
Поэтому лучшее, что вы можете сделать, это приблизить ваш желаемый результат, например, путем получения результата, который не является точной дробью (поплавки, как правило, считаются достаточными для этой цели), а затем дополнительно приблизить его обратно с дробью. Большинство существующих чисто-Python реализаций (есть много rationals.py
файлов, найденных вокруг сети; -) предпочитают вообще не реализовывать * *
оператора, но конечно, ничто не мешает вам принять другое конструкторское решение в вашей собственной реализации! -)
Вы можете написать собственную функцию «POW» для фракций, которые не используют экспоненцию с плавающей точкой. Это то, что вы пытаетесь сделать?
Это поднимет фракцию в целочисленную мощность с паданием на поплавок.
def pow( fract, exp ):
if exp == 0:
return fract
elif exp % 2 == 0:
t = pow( fract, exp//2 )
return t*t
else:
return fract*pos( fract, exp-1 )