Good rational approximations of pi
Golfscript, 71 70 69 chars
2\!:^2^..292^15.2/3]{(.)2/.9>+{\+.((}*;.}do;;]-1%{^0@{2$*+\}/"/"\n}/;
(Assumes that you don't pass it anything on stdin)
I don't want to hear any more whinging by people who don't have built-in constants for pi. I don't even have floating point numbers!
See http://en.wikipedia.org/wiki/Continued_fraction#Best_rational_approximations for the background.
# No input, so the stack contains ""
2\!:^2^..292^15.2/3]
# ^ is used to store 1 because that saves a char by allowing the elimination of whitespace
# Otherwise straightforward: stack now contains [2 1 2 1 1 1 292 1 15 7 3]
# Pi as a continued fraction is 3+1/(7+1/(15+1/(...)))
# If you reverse the array now on the stack you get the first 10 continuants followed by 2
# (rather than 3)
# That's a little hack to avoid passing the denominator 1000000
{
# Stack holds: ... [c_n c_{n-1} ... c_0]
(.)2/.9>+
# Stack holds ... [c_{n-1} ... c_0] c_n (1+c_n)/2+((1+c_n)/2 > 9 ? 1 : 0)
# (1+c_n)/2 > 9 is an ad-hoc approximation of the "half rule"
# which works in this case but not in general
# Let k = (1+c_n)/2+((1+c_n)/2 > 9 ? 1 : 0)
# We execute the next block k times
{
# ... [c_{n-1} ... c_0] z
\+.((
# ... [z c_{n-1} ... c_0] [c_{n-1} ... c_0] z-1
}*
# So we now have ... [c_n c_{n-1} ... c_0] [(c_n)-1 c_{n-1} ... c_0] ...
# [(c_n)-k+1 c_{n-1} ... c_0] [c_{n-1} ... c_0] c_n-k
;
# Go round the loop until the array runs out
.
}do
# Stack now contains all the solutions as CFs in reverse order, plus two surplus:
# [2 1 2 1 1 1 292 1 15 7 3] [1 2 1 1 1 292 1 15 7 3] ... [6 3] [5 3] [4 3] [3] [2] []
# Ditch the two surplus ones, bundle everything up in an array, and reverse it
;;]-1%
# For each CF...
{
# Stack holds ... [(c_n)-j c_{n-1} ... c_0]
# We now need to convert the CF into a rational in canonical form
# We unwind from the inside out starting with (c_n)-j + 1/infinity,
# representing infinity as 1/0
^0@
# ... 1 0 [c_n-j c_{n-1} ... c_0]
# Loop over the terms of the CF
{
# ... numerator denominator term-of-CF
2$*+\
# ... (term-of-CF * numerator + denominator) numerator
}/
# Presentation
"/"\n
# ... numerator "/" denominator newline
}/
# Pop that final newline to avoid a trailing blank line which isn't in the spec
;
Mathematica, 67 63
This isn't going to be fast, but I believe it is technically correct.
Round[π,1/Range@1*^6]//.x_:>First/@Split[x,#2≥#&@@Abs[π-{##}]&]
Round[π, x]
gives the closest fraction to π in steps of x
. This is "listable" so Round[π,1/Range@1*^6]
does this for all fractions down to 1/10^6
in order. The resulting list with many "bad" rational approximations is then repeatedly (//.
) processed by removing any elements which are farther from π than the preceding one.
Perl, 77 chars
$e=$p=atan2 0,-1;($f=abs$p-($==$p*$_+.5)/$_)<$e&&($e=$f,say"$=/$_")for 1..1e6
A minor challenge is that Perl doesn't have a built-in π constant available, so I first had to calculate it as atan2(0,-1)
. I'm sure this will be beaten by languages more suited for the job, but it's not bad for a language mainly designed for text processing.