(EDIT: In response to grumpy comments, No it isn't homework. I am working on pitch detection, taking an array of potential harmonic peaks, and attempting to construct candidates for fundamental frequency. So, it is actually a very practical question.)
Consider the best fractional approximations for (eg) pi, ordered by increasing denominator: 3/1, 22/7, 355/113, ...
Challenge: create a tidy C algorithm that will generate the n'th quotient approximation a/b for a given float, returning also the discrepancy.
calcBestFrac(float frac, int n, int * a, int * b, float * err) {...}
The best technique I believe is continued fractions
Take away the fractional part of pi, and you get 3
Now, the remainder is 0.14159... = 1/7.06251..
So the next best rational is 3 + 1/7 = 22/7
Take away the 7 from 7.06251 and you get 0.06251.. Roughly 1/15.99659..
Call it 16, then the next best approximation is
3 + 1/(7 + 1/16) = 355/113
However, this is far from trivial to convert into clean C code. I will post if I get something tidy. In the meanwhile, someone may enjoy it as a brainteaser.
[Since you asked for this as an answer rather than a comment.]
For any real number, the convergents p[k]/q[k] of its continued fraction are always best rational approximations, but they aren't all the best rational approximations. To get all of them, you also have to take the semi-convergents/mediants — fractions of the form
(p[k]+n*p[k+1])/(q[k]+n*q[k+1])
for some integer n≥1. Taking n=a[k+2] gives p[k+2]/q[k+2], and the integers n to take are those from either floor(a[k+2]/2) or ceiling(a[k+2]/2), to a[k+2]. This is also mentioned on Wikipedia.Approximating π
The continued fraction for π is [3; 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2…] (sequence A001203 in OEIS), the sequence of convergents is 3/1, 22/7, 333/106, 355/113, 103993/33102… (A002485/A002486), and the sequence of best approximations is 3/1, 13/4, 16/5, 19/6, 22/7, 179/57… (A063674/A063673).
So the algorithm says that the best approximations of π = [3; 7, 15, 1, 292, 1, 1,…] are
Program
Here's a C program that given a positive real number, generates its continued fraction, its convergents, and the sequence of best rational approximations. The function
find_cf
finds the continued fraction (putting the terms in a[] and the convergents in p[] and q[] — excuse the global variables), and the functionall_best
prints all the best rational approximations.Examples
For π, here's the output of this program, in about 0.003 seconds (i.e., it's truly better than looping through all possible denominators!), line-wrapped for readability:
All these terms are correct, though if you increase MAX you start getting errors because of precision. I'm myself impressed with how many terms you get with only 13 convergents. (As you can see, there's a small bug where it sometimes doesn't print the very first "n/1" approximation, or prints it incorrectly — I leave it for you to fix!)
You can try with √2, whose continued fraction is [1; 2, 2, 2, 2…]:
Or the golden ratio φ = (1+√5)/2 whose continued fraction is [1; 1, 1, 1, …]:
(See the Fibonacci numbers? Here the convergents are all the approximants.)
Or with rational numbers like 4/3 = [1; 3]:
or 14/11 = [1; 3, 1, 2]:
Enjoy!