Вопрос

Существует ли чистая реализация Python fractions.Fraction который поддерживает longs как числитель и знаменатель?К сожалению, возведение в степень, похоже, закодировано для возврата числа с плавающей запятой (подтверждено!!!), что должно, по крайней мере, поддерживать использование 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'> где ответ должен быть очень маленькой десятичной дробью.

Обновлять:На данный момент у меня есть следующий обходной путь (предполагая, что для a**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 должны быть точными, поэтому неизбежно возникают случаи, когда возведение дроби в степень другой дроби будет абсолютно недопустимо. не могущий вернуть дробь в качестве результата;и слово «должен» просто не может быть разумно применено к математической невозможности.

Поэтому лучшее, что вы можете сделать, это приблизительный желаемый результат, напримерполучая результат, который не является точной дробью (обычно для этой цели достаточно чисел с плавающей запятой), а затем дополнительно аппроксимируя его дробью.Большинство существующих реализаций на чистом 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 )
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top