BigNum -- BigFrac
From: Programmer Dude (Chris_at_Sonnack.com)
Date: 12/23/03
- Next message: Edward G. Nilges: "Re: Letter to US Sen. Byron Dorgan re unpaid overtime"
- Previous message: Programmer Dude: "Re: BigNum -- Floating Point"
- Next in thread: Willem: "Re: BigNum -- BigFrac"
- Reply: Willem: "Re: BigNum -- BigFrac"
- Reply: Paul Hsieh: "Re: BigNum -- BigFrac"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Tue, 23 Dec 2003 11:13:06 -0600
Okay, I'm convinced! I started playing around with BigFracs last
night, and (probably, re-)discovered some fascinating things.
First, checking, do I understand the "basic" or "usual" way this
is done: BigInts as numerator and denominator and a number of
required operations: BigIntAdd(), BigIntMultiply() & gcd(). Also
the internal BigInt storage is binary.
I get the impression from something someone said here that the
stored ratios are normalized--using gcd()--to their lowest
possible values. Presumably, this is to reduce the math that
is required for processing.
Thus, IIU, there might an example like this:
user input:
print 2.5 + 3.14159
initial conversion to BigFracs:
25/10 + 314159/100000
after gcd:
5/2 + 314159/100000
do the add:
(5*100000 + 314159*2) / 2*100000
(500000 + 628318) / 200000
1128318 / 200000
after gcd:
564159/100000
Eventual output in this case is easy with a denominator of 100000,
but--with the design so far (keep reading!)--you can't count on it
being so. Thus the output routine likely involves a BigIntDivide()
operation (I need to review the output code Arthur posted though--
might be a better way?).
All this is fine and not tough to implement, but it does seem this
design requires *three* BigIntMultiply()s and a BigIntAdd(). Even
multiplying appears to require two BigIntMultiply()s. (Or is there
a slicker way to do it?)
What I stumbled on last night appears to remove the need for the
gcd() and the multiply function for add and subtract and removes
one multiply from multiply. (And I'm sure I've just stumbled on
an existing wheel--no great claims of invention here.)
The idea is to keep the denominator as a power of ten, and it's
even possible to remove the BigInt-ness from it if one is willing
to restrict the range to, say, 64 bits worth of powers of ten.
The interesting thing is this "formula":
A/10^ae + B/10^be = (A*10^be-j + B*10^ae-j) / 10^k
Where: j=min(ae,be) and: k=max(ae,be)
What ends up happening is that one of the powers of ten (the lesser)
drops to zero which reduces one side of the addition to identity--
hence no multiply required there. There is also no multiply in the
denominator. The final multiply is *always* a power of ten multiply,
and this can be implemented as a series of left shifts and adds
(surely much faster than an actual multiply!).
So, no gcd(), no multiply.
Returning to the example (ten powers in {}):
print 2.5 + 3.14159
initial conversion to BigFracs:
25/{1} + 314159/{5}
do the add:
j=1; k=5
(25*{5-1} + 314159*{1-1}) / {5}
(25*{4} + 314159*{0}) / {5}
(250000 + 314159) / {5}
564159 / {5}
With the denominator ALWAYS a power of ten, output is always trival.
Multiplication still requires multiplying numerators, but the
"denominators" can just be added.
2.5 * 3.14159
25/{1} * 314159/{5}
25 * 314159/{6}
7853975 /{6}
Division needs work, since inverting the ratio messes up the system.
Still thinking about that one.
But.... thoughts, anyone? It almost seems to combine the goodness
of FP with the goodness of ratios....
-- |_ CJSonnack <Chris@Sonnack.com> _____________| How's my programming? | |_ http://www.Sonnack.com/ ___________________| Call: 1-800-DEV-NULL | |_____________________________________________|_______________________|
- Next message: Edward G. Nilges: "Re: Letter to US Sen. Byron Dorgan re unpaid overtime"
- Previous message: Programmer Dude: "Re: BigNum -- Floating Point"
- Next in thread: Willem: "Re: BigNum -- BigFrac"
- Reply: Willem: "Re: BigNum -- BigFrac"
- Reply: Paul Hsieh: "Re: BigNum -- BigFrac"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|