PEP 327: Decimal Data Type
Josiah Carlson
jcarlson at nospam.uci.edu
Sun Feb 1 14:10:59 EST 2004
> Was your implementation the 'not too bad to get working' or the 'doing
> it well'?
I thought it did pretty well. But then again, I didn't really much
worry about it or use it much. I merely tested to make sure it did the
right thing and forgot about it.
> For instance, there is the greatest common divisor that you need for
> normalising the rationals.
>
> I used the Euclidean algorithm for the GCD. Not too bad, certainly
> better than using prime factorisation, but as I understand it doing
> the job well means using a better algorithm for this - though I never
> did bother looking up the details.
I also used Euclid's GCD, but last time I checked, it is a pretty
reasonable algorithm. Runs in log(n) time, where n is the maximum of
either value. Technically, it runs linear in the amount of space that
it takes up, which is about as well as you can do.
> Actually, as far as I remember, just doing the arbitrary length
> integer division functions took me more than your 45 minutes. The long
> division algorithm is simple in principle, but I seem to remember
> messing up the decision of how many bits to shift the divisor after a
> subtraction. Of course in Python, that's already done.
Ahh, integer division. I solved a related problem with long integers
for Python in a programming competition my senior year of college
(everyone else was using Java, the suckers) in about 15 minutes. We
were to calculate 1/n, for some arbitrarily large n (where 1/n was a
fraction that could be represented by base-10 integer division). Aside
from I/O, it was 9 lines.
Honestly, I never implemented integer division in my rational type. For
casts to floats,
float(self.numerator)/float(self.denominator)+self.whole seemed just
fine (I was using rationals with denominators in the range of 2-100 and
total value < 1000).
Thinking about it now, it wouldn't be very difficult to pull out my 1/n
code and adapt it to the general integer division problem. Perhaps
something to do later.
> Maybe I was just having a bad day. Maybe I remember it worse than it
> really was. Still, 45 minutes doesn't seem too realistic in my memory,
> even for the 'not too bad to get working' case.
For all the standard operations on a rational type, all you need is to
make sure all you have is two pairs of numerators and denominators, then
all the numeric manipulation is trivial:
a.n = a.numerator * a.whole*a.denominator
a.d = a.denominator
b.n = b.numerator * b.whole*b.denominator
b.d = b.denominator
a + b = rational(a.n*b.d + b.n*a.d, a.d*b.d)
a - b = rational(a.n*b.d - b.n*a.d, a.d*b.d)
a * b = rational(a.n*b.n, a.d*b.d)
a / b = rational(a.n*b.d, a.d*b.n)
a ** b, b is an integer >= 1 (binary exponentiation)
One must remember to normalize on initialization, but that's not
difficult. Functionally that's how my rational turned out. It wasn't
terribly full featured, but it worked well for what I was doing.
- Josiah
More information about the Python-list
mailing list