3 ms·
Yes. Continued fractions offer the best possible rational approximations, for some definition of distance which I don't remember at this moment. Moreover, they
by crdrost 5y ago
Yes. Continued fractions offer the best possible rational approximations, for some definition of distance which I don't remember at this moment.
Moreover, they are uncommonly good if you truncate just before a large integer. So for π, 22/7 is a great approximation because the next number in the continued fraction is 15, but it is blown out of the water by 355/113 which is not specified to only ~0.3% accuracy as you might expect from the denominator, but rather 0.000008%. This comes from the splendidly large next integer 292.
e is more boring, the continued fraction is [2; 1, 2, 1, 1, 4, 1, 1, 6, ...], and that pattern indeed repeats forever. So you do keep getting these large integers, and they keep getting larger. That first one was 19/7 (0.1%), then 193/71 (0.001%), then 2721/1001 (0.000004%), then 49171/18089, which has about the same error as your approximation, but less than 1/5 of the denominator. So the continued fraction doesn't pick that one up because as far as the continued fraction is concerned it's not very good :D
Side note: It turns out that the above computational approach of "build continued fraction and then evaluate it" is not necessary and you can actually stream these. So you can take a + 1/(b + 1/(c + 1/x)) and rephrase it as sort of f_a(f_b(f_c(x)))). Simplifying by just looking at
> f_c(m/n) = c + n/m = (c m + 1 n)/(1 m + 0 n)
we can rewrite this as a matrix product,
[ a 1 ] * [ b 1 ] * [ c 1 ] * [ m ]
[ 1 0 ] [ 1 0 ] [ 1 0 ] [ n ]
and the nice thing about matrices is that their multiplication is associative, so we can compute front-to-back instead of back-to-front:
Prelude> (a, b, c, d) .* (w, x, y, z) = (a*w + b*y, a*x + b*z, c*w + d*y, c*x + d*z) :: (Integer, Integer, Integer, Integer)
Prelude> (2, 1, 1, 0) .* (1, 1, 1, 0) .* (2, 1, 1, 0) .* (1, 1, 1, 0) .* (1, 1, 1, 0) -- starting point
(19,11,7,4)
Prelude> let matrices = scanl (\matrix n -> matrix .* (n,1,1,0) .* (1, 1, 1, 0) .* (1, 1, 1, 0)) (19, 11, 7, 4) [4,6..]
Prelude> take 5 matrices
[(19,11,7,4),(193,106,71,39),(2721,1457,1001,536),(49171,25946,18089,9545),(1084483,566827,398959,208524)]
Prelude>
Prelude> :m +Data.Ratio
Prelude Data.Ratio> take 8 $ map (\(a, b, c, d) -> a % c) matrices
[19 % 7,193 % 71,2721 % 1001,49171 % 18089,1084483 % 398959,28245729 % 10391023,848456353 % 312129649,28875761731 % 10622799089]
note that this is streaming due to the scanl, so it'll compute the next term in O(1) given the last terms. (Also note that there are some other "best approximations" hidden in there because I am taking this by these [4, 1, 1] then [6, 1, 1] then [8, 1, 1] chunks.)
Side side note: it also follows that the most irrational number is 1 + 1/(1 + 1/(1 + 1/(1 + ...))) for this metric of distance, as it always has the smallest possible number in its continued fractions; its approximants are never "very good". Solving for φ = 1 + 1/φ and some quadratic formula reveals this as the golden ratio φ = (1 + √5)/2. If you do this process you will find that the matrix always contains Fibonacci numbers and this matrix [1, 1; 1 0] kind of encodes the Fibonacci recurrence directly.