Части с десятичной точностью

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

6
задан Noah 11 January 2010 в 00:25
поделиться

2 ответа

«Поднять в степень» не является замкнутой операцией над рационалями (иначе, чем обычные четыре арифметические операции): нет рационального числа r такого, что r = = 2 * * 0,5 . Легенда гласит, что Пифагор (из теоремы которого этот факт так просто следует) убил своего ученика Гиппаса за ужасное преступление доказать это; похоже, вы сочувствуете предполагаемой реакции Пифагора; -), учитывая ваше странное использование «должен».

Фракции Пайтона должны быть точными, поэтому неизбежно имеют место случаи, когда возведение фракции в степень другой фракции будет абсолютно неспособным вернуть фракцию в ее результате; и «должен» просто не может быть разумно применен к математической невозможности.

Поэтому лучшее, что вы можете сделать, это приблизить ваш желаемый результат, например, путем получения результата, который не является точной дробью (поплавки, как правило, считаются достаточными для этой цели), а затем дополнительно приблизить его обратно с дробью. Большинство существующих чисто-Python реализаций (есть много rationals.py файлов, найденных вокруг сети; -) предпочитают вообще не реализовывать * * оператора, но конечно, ничто не мешает вам принять другое конструкторское решение в вашей собственной реализации! -)

6
ответ дан 17 December 2019 в 02:29
поделиться

Вы можете написать собственную функцию «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 )
0
ответ дан 17 December 2019 в 02:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: