# pi的良好有理逼近

22

``````3/1
13/4
16/5
19/6
22/7
179/57
...
833719/265381
1146408/364913
3126535/995207
``````

23

## Golfscript，71 70 69个字符

``````2\!:^2^..292^15.2/3]{(.)2/.9>+{\+.((}*;.}do;;]-1%{^0@{2\$*+\}/"/"\n}/;
``````

（假设您没有在stdin上传递任何内容）

``````# 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
;
``````

1

2
@GlitchMr，字符串以什么方式是浮点数？

2012年

primo 2012年

@PeterTaylor 。我们可以做得更好吗？
Eelvex 2014年

11

## Mathematica，67 63

``````Round[π,1/Range@1*^6]//.x_:>First/@Split[x,#2≥#&@@Abs[π-{##}]&]
``````

`Round[π, x]`给出最接近π的分数（步长为）`x`。这是“可列出的”，因此`Round[π,1/Range@1*^6]`对所有分数`1/10^6`按顺序排列都是如此。然后，`//.`通过删除距离π比前一个元素更远的任何元素来重复（）处理具有许多“不良”有理近似值的结果列表。

@Keith，这是逻辑。 在的步长中`Round[Pi, x]`给出最接近的分数。这是“可列出的”，因此对于所有小到1/10 ^ 6的分数都是如此。然后，通过删除比pi更远离pi的任何元素来重复（）处理具有许多“不良”有理近似值的结果列表。`Pi``x``Round[Pi,1/Range@1*^6]``//.`

Mathematica击败了GolfScript。整齐。
SpellingD 2012年

61：`Select[Round[f=Pi,1/Range@1*^6],If[#<f,f=#;True]&@Abs[#-Pi]&]`... ...但由于主要偏见而无用
belisarius博士2014年

Yarr，Matie。在此代码中，变魔术。
Michael Stern

7

## Perl，77个字符

``````\$e=\$p=atan2 0,-1;(\$f=abs\$p-(\$==\$p*\$_+.5)/\$_)<\$e&&(\$e=\$f,say"\$=/\$_")for 1..1e6
``````

1

Toto

@ M42：谢谢！现在降至82个字符。
Ilmari Karonen 2011年

Keith Randall

@KeithRandall：您需要`-M5.01`用于`say`命令的开关（以及Perl 5.10.0或更高版本）。对不起，我没有提及。
Ilmari Karonen 2011年

5

## Python，96 93 89个字符

``````a=b=d=1.
while b<=1e6:
e=3.14159265359-a/b;x=abs(e)
if x<d:print a,b;d=x
a+=e>0;b+=e<0
``````

### Python中，95 93个字符，不同的算法

``````p=3.14159265359;d=1
for a in range(3,p*1e6):
b=round(a/p);e=abs(p-a/b)
if e<d:print a,b;d=e
``````

1

Keith Randall

@KeithRandall，但是其中第二个使输出违反规范。

@PeterTaylor：我不明白。它如何违反规范？
Steven Rumbalski 2011年

4

## JS（95个字符）

``````for(i=k=1,m=Math;i<1e6;i++)if((j=m.abs((x=m.round(m.PI*i))/i-m.PI))<k)k=j,console.log(x+'/'+i)
``````

4

### Ruby 1.9，84个字符

``````m=1;(1..1e6).map{|d|n=(d*q=Math::PI).round;k=(n-q*d).abs/d;k<m&&(m=k;puts [n,d]*?/)}
``````

@Peter Taylor你是对的。您必须使用Ruby 1.9。

4

## C99，113个字符

``````main(d,n){double e=9,p=2*asin(1),c,a=1;for(;n=d*p+.5,c=fabsl(p-a*n/d),d<1e6;++d)c<e&&printf("%d/%d\n",n,d,e=c);}
``````

2

### Scala-180个字符

``````import math._
def p(z:Int,n:Int,s:Double):Unit=
if(n==1e6)0 else{val q=1.0*z/n
val x=if(abs(Pi-q)<s){println(z+"/"+n)
abs(Pi-q)}else s
if(Pi-q<0)p(z,n+1,x)else p(z+1,n,x)}
p(3,1,1)
``````

//取消高尔夫：457

``````val pi=math.Pi
@annotation.tailrec
def toPi (zaehler: Int = 3, nenner: Int = 1, sofar: Double=1): Unit = {
if (nenner == 1000000) ()
else {
val quotient = 1.0*zaehler/nenner
val diff = (pi - quotient)
val next = if (adiff < sofar) {
println (zaehler + "/" + nenner)
}
else sofar
if (diff < 0) toPi (zaehler, nenner + 1, next)
else toPi (zaehler + 1, nenner, next)
}
}
``````

tailrec批注只是一种检查，以验证它是否为尾递归，这通常是性能上的改进。

Keith Randall

simplescala.com上尝试-对我有用。斯卡拉-2.8，替换`math``Math`可能就足够了。我在此元线程上提到过simplescala，如果您碰巧要再次搜索它：meta.codegolf.stackexchange.com/a/401/373

2

# Mathematica 18 17个字符

``````Convergents[π, 10]

(* out *)
{3, 22/7, 333/106, 355/113, 103993/33102, 104348/33215, 208341/66317,
312689/99532, 833719/265381, 1146408/364913}
``````

``````Convergents[π, 10] /. {3 -> "3/1"}
(* out *)
{"3/1", 22/7, 333/106, 355/113, 103993/33102, 104348/33215,
208341/66317, 312689/99532, 833719/265381, 1146408/364913}
``````

``````Table[ContinuedFraction[π, k], {k, 10}]
w[frac_] := Row[{Fold[(#1^-1 + #2) &, Last[#], Rest[Reverse[#]]] &[Text@Style[#, Blue, Bold, 14] & /@ ToString /@ ContinuedFraction[frac]]}];
w /@ FromContinuedFraction /@ ContinuedFraction /@ Convergents[π, 10]
``````

DavidC 2012年

1

# C＃140 129个字符

``````double n=3,d=1,e=d;while(n<4e5){double w=n/d-Math.PI,a=Math.Abs(w);if(a<e){e=a;Console.WriteLine(n+"/"+d);}if(w>0)d++;else n++;}
``````

``````var numerator = 3d;
var denominator = 1d;
var delta = 4d;
while (numerator < 4e5)
{
var newDelta = (numerator / denominator) - Math.PI;
var absNewDelta = Math.Abs(newDelta);
if (absNewDelta < delta)
{
delta = absNewDelta;
Console.WriteLine(string.Format("{0}/{1}", numerator, denominator));
}

if (newDelta > 0)
{
denominator++;
}
else
{
numerator++;
}
}
``````

2
`var`并不总是你的朋友。通过删除它有利于`double`您获得合并声明的能力，无需使用双字面量，并且可以节省16个字符。OTOH问题要求一个程序，因此添加类声明和`Main`方法将使您不知所措。

1

# J，69 65

### 新

``````]`,@.(<&j{.)/({~(i.<./)@j=.|@-l)@(%~(i:3x)+<.@*l=.1p1&)"0>:_i.1e3
``````

### 旧

``````(#~({:<<./@}:)\@j)({~(i.<./)@j=.|@-l)@(%~(i:6x)+<.@*l=.1p1&)"0>:i.1e3
``````