Is there a pure python implementation of fractions.Fraction
that supports long
s as numerator and denominator? Unfortunately, exponentiation appears to be coded in to return a float (ack!!!), which should at least support using decimal.Decimal
.
If there isn't, I suppose I can probably make a copy of the library and try to replace occurrences of float()
with something appropriate from Decimal
but I'd rather something that's been tested by others before.
Here's a code example:
base = Fraction.from_decimal(Decimal(1).exp())
a = Fraction(69885L, 53L)
x = Fraction(9L, 10L)
print base**(-a*x), type(base**(-a*x))
results in 0.0 <type 'float'>
where the answer should be a really small decimal.
Update: I've got the following work-around for now (assuming, for a**b, that both are fractions; of course, I'll need another function when exp_ is a float or is itself a Decimal):
def fracpow(base, exp_):
base = Decimal(base.numerator)/Decimal(base.denominator)
exp_ = Decimal(exp_.numerator)/Decimal(exp_.denominator)
return base**exp_
which gives the answer 4.08569925773896097019795484811E-516.
I'd still be interested if there's a better way of doing this without the extra functions (I'm guessing if I work with the Fraction
class enough, I'll find other floats working their way into my results).
"Raise to a power" is not a closed operation over the rationals (differently from the usual four arithmetic operations): there is no rational number r
such that r == 2 ** 0.5
. Legend has it that Pythagoras (from whose theorem this fact so simply follows) had his disciple Hippasus killed for the horrible crime of proving this; looks like you sympathize wit Pythagoras' alleged reaction;-), given your weird use of "should".
Python's fractions are meant to be exact, so inevitably there are case in which raising a fraction to another fraction's power will be absolutely unable to return a fraction as its result; and "should" just cannot be sensibly applied to a mathematical impossibility.
So the best you can do is to approximate your desired result, e.g. by getting a result that's not an exact fraction (floats are generally considered sufficient for the purpose) and then further approximating it back with a fraction. Most existing pure-Python implementations (there are many rationals.py
files found around the net;-) prefer not to implement a **
operator at all, but of course there's nothing stopping you from making a different design decision in your own implementation!-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With