Domanda

C'è un'implementazione pitone puro fractions.Fraction che supporta longs come numeratore e denominatore? Purtroppo, l'elevamento a potenza sembra essere codificato in per restituire un float (ACK !!!), che dovrebbe almeno il supporto utilizzando decimal.Decimal.

Se non c'è, suppongo che posso probabilmente fare una copia della biblioteca e provare a sostituire le occorrenze di float() con qualcosa di appropriato da Decimal ma preferirei qualcosa che è stato testato da altri prima.

Ecco un esempio di codice:

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

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

risultati in 0.0 <type 'float'> in cui la risposta dovrebbe essere davvero un piccolo decimale.

Aggiorna : ho ottenuto il seguente work-around per ora (assumendo, per un ** B, che entrambi sono frazioni, naturalmente, avrò bisogno di un'altra funzione quando exp_ è un galleggiante o è essa stessa un decimale):

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

    return base**exp_

che dà la risposta 4.08569925773896097019795484811E-516.

Sarei ancora interessato se c'è un modo migliore di fare questo senza le funzioni supplementari (sto cercando di indovinare se lavoro con la classe Fraction abbastanza, troverò altri carri che lavorano la loro strada nei miei risultati).

È stato utile?

Soluzione

"Alza ad una potenza" non è un'operazione chiusa sopra razionali (diversamente dai soliti quattro operazioni aritmetiche): non c'è un numero razionale r tale che r == 2 ** 0.5. La leggenda narra che Pitagora (da cui il teorema questo fatto segue in modo così semplice) ha avuto il suo discepolo Ippaso ucciso per l'orrendo crimine di provare questo; Sembra che simpatizzare wit presunta reazione di Pitagora ;-), dato l'utilizzo di strano 'dovrebbe'.

frazioni di Python sono destinate ad essere esatti, quindi inevitabilmente ci sono casi in cui sollevare una frazione della potenza di un'altra frazione sarà assolutamente non per tornare una frazione come risultato; e "dovrebbe" semplicemente non può essere ragionevolmente applicata ad un'impossibilità matematica.

Quindi la cosa migliore che puoi fare è quello di approssimativa il risultato desiderato, per esempio ottenendo un risultato che non è una frazione esatta (galleggianti sono generalmente considerati sufficienti per lo scopo) e poi ravvicinare ulteriormente indietro con una frazione. La maggior parte delle attuali implementazioni puro-Python (ci sono molti file rationals.py trovato intorno alla rete ;-) preferiscono non implementare un operatore ** a tutti, ma ovviamente non c'è nulla ti impedisce di prendere una decisione in design diverso la propria implementazione -!)

Altri suggerimenti

È possibile scrivere la propria funzione "pow" per frazioni che non utilizzano in virgola mobile elevamento a potenza. E 'questo che stai cercando di fare?

Questo solleverà una frazione di una potenza intera con ricadere a galleggiare.

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 )
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top