Pergunta

Existe uma implementação python puro de fractions.Fraction que suporta longs como numerador eo denominador? Infelizmente, a exponenciação parece estar codificado em retornar um float (ack !!!), que deve pelo menos de suporte usando decimal.Decimal.

Se não é, suponho eu provavelmente pode fazer uma cópia da biblioteca e tentar substituir ocorrências de float() com algo apropriado de Decimal mas eu prefiro algo que tem sido testado por outros antes.

Aqui está um exemplo de código:

base = Fraction.from_decimal(Decimal(1).exp())
a = Fraction(69885L, 53L)
x = Fraction(9L, 10L)

print base**(-a*x), type(base**(-a*x))

resulta em 0.0 <type 'float'> onde a resposta deve ser realmente um pequeno decimal.

Atualizar : Eu tenho a seguinte solução alternativa para agora (supondo que, para uma b **, que ambos são frações, claro, eu vou precisar de outra função quando exp_ é um flutuar ou é em si um Decimal):

def fracpow(base, exp_):
    base = Decimal(base.numerator)/Decimal(base.denominator)
    exp_ = Decimal(exp_.numerator)/Decimal(exp_.denominator)

    return base**exp_

que dá a resposta 4.08569925773896097019795484811E-516.

eu ainda estaria interessado em saber se há uma maneira melhor de fazer isso sem as funções extras (eu estou supondo que se eu trabalhar com o suficiente classe Fraction, eu vou encontrar outros carros alegóricos trabalhando sua maneira em meus resultados).

Foi útil?

Solução

"Raise a um poder" não é uma operação fechada sobre os racionais (diferente do habitual quatro operações aritméticas): não há nenhum número racional r tal que r == 2 ** 0.5. Diz a lenda que Pitágoras (de cujo teorema este fato tão simplesmente segue) teve seu discípulo Hippasus matou pelo crime horrível de provar isso; Parece que você simpatizar sagacidade Pitágoras alegada reação ;-), dada a sua utilização estranha de 'deveria'.

frações do Python são feitos para ser exato, por isso, inevitavelmente, há casos em que levantar uma fração do poder de outra fração será absolutamente não para retornar uma fração como seu resultado; e "deve" simplesmente não pode ser sensivelmente aplicada a uma impossibilidade matemática.

Então, o melhor que você pode fazer é aproximado o resultado desejado, por exemplo, obtendo um resultado que não é uma fração exata (flutuadores são geralmente considerado suficiente para o efeito) e, em seguida, ainda aproximando-o de volta com uma fração. A maioria das implementações puro-Python existentes (não são muitos arquivos rationals.py encontrados em torno da rede ;-) preferem não implementar um operador ** em tudo, mas é claro que não há nada que você parar de tomar uma decisão design diferente em sua própria implementação -!)

Outras dicas

Você pode escrever sua própria função "prisioneiro de guerra" para as frações que não usam exponenciação de ponto flutuante. É isso que você está tentando fazer?

Isso vai elevar uma fração a uma potência inteira com a queda de volta para float.

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 )
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top