[Tutor] Need help with rewriting script to use Decimal module
Danny Yoo
dyoo at hkn.eecs.berkeley.edu
Wed Jan 3 22:41:12 CET 2007
>> Dick, if your goal is to have a routine to get the fraction with the least
>> possible error (as opposed to learing how to use Decimal), have a look at
>> this recipe from the Python Cookbook:
>>
>> http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52317
>
> Terry, that is truly ingenious. Is there an explication anywhere of
> exactly how it works?
Hi Dick,
On a first glance, it looks like it's doing a binary search on the Farey
series on some order. (Actually, it's not, but we'll get to that later in
this post.) Farey sequences have an entry on Wikipedia:
http://en.wikipedia.org/wiki/Farey_number
Look at the terms of F_8, for example. If you take two points with some
other point between them, say 1/5 and 2/7, notice that:
1 3 2
- < -- < -
5 12 7
If we just do the funny thing by adding the numerators and denominators
--- by taking the "mediant" --- we end up with another term in the Farey
sequence. This is very cute.
Wait. Actually, what the algorithm is doing doesn't appear to be
searching through a particular Farey sequence of order n. Instead, what
it's doing is much simpler: it appears to be just taking advanatage of the
in-betweenness property of "mediants".
http://en.wikipedia.org/wiki/Mediant_%28mathematics%29
Oh well, that still works. The algorithm seems to be misnamed, though: I
think it should really be described as "inexact to rational via mediant
approximation."
The trick that the algorithm is really a binary-search, using the
definition of "mediant" to find "midpoints". Whenever we see something
like:
####################################################################
while we haven't found the answer:
We know that the answer's somewhere between the lower and upper
bounds. (precondition)
midpoint = some calculation combining the lower and upper bounds
if the midpoint is too big:
move the upper bound
elif the midpoint is too small:
move the lower bound
else
we've found the answer
At the end of this, we guarantee our answer's still between
the lower and upper bounds. (postcondition)
####################################################################
then we should suspect a binary search. In the case of the algorithm in
the Cookbook, we can see that it follows this structure very closely.
Concretely, when they say:
if v * mediant[1] > mediant[0]: ...
we can do simple equational reasoning to see that this is really
saying:
if v > (mediant[0] / mediant[1]): ...
aka: "if the value we're looking for is bigger than the mediant, move the
lower bound up." The mediant is being represented by a 2-tuple
(numerator, denominator), so with that, you should be able to read the
case analysis off more easily.
Best of wishes!
More information about the Tutor
mailing list