Rational approximation methods
In the Rational class that I've recently checked into Python 2.6 (http://bugs.python.org/issue1682), it might be nice to provide a method that, given a particular rational number, returns a nearby number that's nicer in some way. I know of two reasonable behaviors for this operation. Since I don't know which is likely to be more useful, or even if either is useful enough to include in the first version of the module, I'm coming to you guys for advice. Both were implemented a while ago in http://svn.python.org/view/sandbox/trunk/rational/Rational.py?rev=40988&view=markup and are based on the continued fraction representation of the number (http://en.wikipedia.org/wiki/Continued_fraction#Best_rational_approximations). The first returns the closest rational whose denominator is less than a given integer. For discussion, we might call it .limit_denominator(), although I'm also looking for good names. This seems useful for computations in which you want to sacrifice some accuracy for speed. On the other hand, Decimal may fill the niche for fast-ish computation that surprises people less than float. The second returns the simplest rational within some distance. For instance, it'll prefer 22/7 over 333/106 if both are close enough. We might call it .simplest_within() for now. This seems useful for converting from float and displaying results to users, where we prefer readability over accuracy or have reason to believe that a simpler fraction might be more correct. What does the list think? Jeffrey
The second returns the simplest rational within some distance. For instance, it'll prefer 22/7 over 333/106 if both are close enough. We might call it .simplest_within() for now. This seems useful for converting from float and displaying results to users, where we prefer readability over accuracy or have reason to believe that a simpler fraction might be more correct. You can use a mediant walk to get to two surrounding fractions w/ some
Jeffrey Yasskin wrote: limit, and then return the pair to let the caller choose. See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52317 for an imperfect implementation.
On Jan 19, 2008 3:06 PM, Jeffrey Yasskin
In the Rational class that I've recently checked into Python 2.6 (http://bugs.python.org/issue1682), it might be nice to provide a method that, given a particular rational number, returns a nearby number that's nicer in some way. I know of two reasonable behaviors [...] What does the list think?
I'm having trouble imagining a real use case for either of these methods. When I'm using Rational, it's almost certainly because I want exact arithmetic; if I'm getting results with huge denominators and numerators then either that's what I really want, or I probably shouldn't have been using Rational in the first place... The only semi-use case I see is providing some way for users to turn the float 1.1 into the rational 11/10, instead of Rational(2476979795053773L,2251799813685248L). So I'd say leave both these methods out for now---it would be easy enough to add them later if it turns out there's a real need. Just my 200/391 UK pennies :) Mark
On 19/01/2008, Jeffrey Yasskin
The first returns the closest rational whose denominator is less than a given integer. [...] The second returns the simplest rational within some distance.
Both of these are likely to be of limited use. The most common usage I know of is to make a "sensible" rational from a float (i.e., a DWIM style conversion 0.1 -> 1/10) or to provide readable output. On the other hand, both are subtle to implement, so having a standard implementation saves people having to code (and debug) their own. I suspect that simplest within a particular distance is the form that is most often wanted, but I don't have any good evidence for that feeling. Putting both in might help people to realise that there *is* a choice. Given that you have implemented them, I'd say leave them in. And I like the names trim and approximate, as given in the code you referenced. Paul.
On 1/20/08, Paul Moore
Both of these are likely to be of limited use. The most common usage I know of is to make a "sensible" rational from a float (i.e., a DWIM style conversion 0.1 -> 1/10) or to provide readable output. On the other hand, both are subtle to implement, so having a standard implementation saves people having to code (and debug) their own.
I suspect that simplest within a particular distance is the form that is most often wanted, but I don't have any good evidence for that feeling. Putting both in might help people to realise that there *is* a choice.
Given that you have implemented them, I'd say leave them in. And I like the names trim and approximate, as given in the code you referenced.
I can't think of a use case for these either, but the first (limit_denominator) seems like a generalized round, and I suppose might be useful for something. -- Cheers, Leif
What would be useful is a method that generates (i.e., a generator in the Python sense) the (continued fraction) convergents to a rational. People wanting specific constraints on a rational approximation (including, but not limited to, the two you identified) can easily build them on top of such a generator. By "useful" I don't mean lots of people will use it ;-) I mean /some/ people will use it -- a way to generate the sequence of convergents is a fundamental tool that can be used for all sorts of stuff, by those with advanced applications.
On 21/01/2008, Tim Peters
What would be useful is a method that generates (i.e., a generator in the Python sense) the (continued fraction) convergents to a rational. People wanting specific constraints on a rational approximation (including, but not limited to, the two you identified) can easily build them on top of such a generator.
Interesting. I thought of suggesting something like this, but my potential use cases are so rare that I couldn't justify it. But as you say, it's one general building block from which any other desired functionality can be produced.
By "useful" I don't mean lots of people will use it ;-) I mean /some/ people will use it -- a way to generate the sequence of convergents is a fundamental tool that can be used for all sorts of stuff, by those with advanced applications.
Good point. Fundamental tools belong in the library. +1 Paul.
On Jan 21, 2008 3:44 AM, Paul Moore
On 21/01/2008, Tim Peters
wrote:> By "useful" I don't mean lots of people will use it ;-) I mean /some/ people will use it -- a way to generate the sequence of convergents is a fundamental tool that can be used for all sorts of stuff, by those with advanced applications.
Good point. Fundamental tools belong in the library. +1
How about a generator for the convergents in the rational module together with an example in the documentation showing how to use the convergents to implement something like trim?
On Jan 20, 2008 5:54 PM, Tim Peters
What would be useful is a method that generates (i.e., a generator in the Python sense) the (continued fraction) convergents to a rational. People wanting specific constraints on a rational approximation (including, but not limited to, the two you identified) can easily build them on top of such a generator.
I think that's significantly better than my two proposals. (Looking back at the issue, I see that Mark mentioned this possibility too and I just didn't understand him.) I'll plan on implementing that, along with the documentation Mark suggested, unless there are objections. Thanks! Jeffrey
participants (6)
-
Jeffrey Yasskin
-
Leif Walsh
-
Mark Dickinson
-
Paul Moore
-
Scott David Daniels
-
Tim Peters