[Tutor] Need help with rewriting script to use Decimal module
Terry Carroll
carroll at tjc.com
Mon Jan 8 03:32:54 CET 2007
On Sat, 6 Jan 2007, Dick Moores wrote:
> Well, I have to admit I don't understand your code at all. But I see it
> works.
A continuing fraction is an expression that looks like this:
1
A + ----------------------------------
1
B + -----------------------------
1
C + ----------------------
1
D + -----------------
E + etc.
i.e., A + (1 / (B + (1 / (C + (1 / (D + (1 / E + ... )))))))
That is, the denominator of the fraction itself has a term that is a
fraction; and that fraction itself has a term that is a fraction, etc.,
either to infinity or to some finite point.
The basic idea of using a continued fraction to get a rational
approximation is something like this. Say you want to get an
approximation of 0.096. Well, a good first approximation is 1/10. But
1/10 is 0.010. That's too big, or, to put another way, the denominator is
too small. It should really be 1/(10+something), where "something" is
some fraction 1/x (if it were larger than 1, then we'd be starting from
11+ something).
The next best approximation is to figure out that "something" is. It
turns out, it's 1/2, i.e. .096 = about 1/(10+(1/2)), or about 0.9624.
That's still too big, so that 1/2 we added should really be 1/(2+
something).
The next "something" we calculate is again 1/2, so it's
1/(10+(1/(2+(1/2)), or .096154. Getting closer, but the same thing.
Again, the next something is 1/2, so we get 1/(10+(1/(2+(1/(2+1/2))),
which is 0.096, exactly.
So, in that butt-ugly ascii I have above, A=10, B = 2, C = 2 and D = 2,
and it turns out not to have been necessary to go any further.
(I admit I cheated above and picked 0.096 as an example, because some
other examples, like .093 and .098 actually have a "something" that's
equal to 1).
Now, I actually don't understand all of the math in the article at
http://mathworld.wolfram.com/ContinuedFraction.html , which I based this
on; but enough of it is clear that I could basically just take certain
equations and translate them into Python:
> a, r, p, q = [], [], [], []
This is a list of terms; "a" is the successive denominator, i.e. compared
to my description above a[0] is A; a[1] is B; a[2] is C, etc. r[n] is
used to calculate a[n]; it actually could have been dispensed with. p[n]
and q[n] are the value of the continued fraction after n iterations.
> a.append(None)
> r.append(None)
> p.append(None)
> q.append(None)
This is just so I can assign to a[n], r[n], etc.; it makes the code more
readable.
> if n == 0: r[n] = x
> else: r[n] = 1/(r[n-1]-a[n-1])
These statements are equations 8 & 9 from the Wolfram page cited above.
> a[n] = int(r[n])
This is equation 10.
> if n == 0:
> p[n] = a[0]
> q[n] = 1
These are effectively equations 25 & 26 for the special case of n == 0,
i.e. equation 24.
> elif n ==1:
> p[n] = a[n]*p[n-1] + 1
> q[n] = a[n]
These are equations 25 & 26 for the special case of n == 1, taking into
account equations 22 to get values for what would have otherwise looking
for p[-1], i.e. an entry before the first element in the list.
> else:
> p[n] = a[n]*p[n-1] + p[n-2]
> q[n] = a[n]*q[n-1] + q[n-2]
This is the general case for equations 25 & 26.
The rest is just cranking through the iterations.
> (BTW your pi is a bit off but I used yours, instead of math.pi, which
> is 3.1415926535897931 .
Oops. I transposed the "79" and "89"; that's what I get for going from
memory.
I may add this algorithm to the cookbook.
More information about the Tutor
mailing list