답변:
2\!:^2^..292^15.2/3]{(.)2/.9>+{\+.((}*;.}do;;]-1%{^0@{2$*+\}/"/"\n}/;
(stdin에 아무것도 전달하지 않는다고 가정)
파이에 대한 상수가없는 사람들이 더 이상 징징 거리는 소리를 듣고 싶지 않습니다. 부동 소수점 숫자조차 없습니다!
배경 은 http://en.wikipedia.org/wiki/Continued_fraction#Best_rational_approximations 를 참조하십시오 .
# 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
;
2\!:^2^..292^15.2/3]
이미 내 마음을 불었다.
이것은 빠르지는 않지만 기술적으로 정확하다고 생각합니다.
Round[π,1/Range@1*^6]//.x_:>First/@Split[x,#2≥#&@@Abs[π-{##}]&]
Round[π, x]
의 단계에서 π에 가장 가까운 분수를 제공합니다 x
. 이것은 "목록"이므로 Round[π,1/Range@1*^6]
모든 분수 1/10^6
에 대해 순서 대로이 작업을 수행합니다 . 많은 "나쁜"합리적인 근사치가있는 결과 목록 //.
은 이전 요소보다 π에서 더 멀리있는 요소를 제거 하여 반복적으로 처리됩니다 ( ).
Round[Pi, x]
의 Pi
단계에서 가장 가까운 분수를 제공합니다 x
. 이것은 "listable"이므로 Round[Pi,1/Range@1*^6]
1 / 10 ^ 6까지의 모든 분수에서 순서 대로이 작업을 수행합니다. 많은 "나쁜"합리적인 근사치가있는 결과 목록 //.
은 이전의 것보다 pi에서 더 멀리있는 요소를 제거 하여 반복적으로 처리됩니다 ( ).
Select[Round[f=Pi,1/Range@1*^6],If[#<f,f=#;True]&@Abs[#-Pi]&]
... 그러나 지배적 인 편견이 주어지면 쓸모가 없습니다
$e=$p=atan2 0,-1;($f=abs$p-($==$p*$_+.5)/$_)<$e&&($e=$f,say"$=/$_")for 1..1e6
사소한 문제는 Perl에 내장 π 상수가 없기 때문에 먼저로 계산해야한다는 것 atan2(0,-1)
입니다. 나는 이것이 직업에 더 적합한 언어에 의해 이길 것이라고 확신하지만, 주로 텍스트 처리를 위해 설계된 언어에는 나쁘지 않습니다.
999999
에 1e6
3 개 문자를 저장합니다.
String found where operator expected at prog.pl line 1, near "say"$=/$_""
-M5.01
스위치 (및 Perl 5.10.0 이상)가 필요합니다 say
. 언급하지 않아서 죄송합니다.
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
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
참고 : 쓰는 p=3.14159265359;
것보다 문자가 적었 습니다 from math import*
. 그 장엄한 수입품을 !!
1.0
-> 1.
, 10**6
->1e6
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 adiff= math.abs (diff)
val next = if (adiff < sofar) {
println (zaehler + "/" + nenner)
adiff
}
else sofar
if (diff < 0) toPi (zaehler, nenner + 1, next)
else toPi (zaehler + 1, nenner, next)
}
}
tailrec 주석은 꼬리 재귀인지 확인하기위한 점검 일 뿐이며, 이는 종종 성능 향상입니다.
pi.scala:1 error: not found: value math
math
로하는 것은 Math
충분히있을 수 있습니다. 이 메타 스레드에 대해 간단히 스칼라를 언급했는데, 다시 검색하면 meta.codegolf.stackexchange.com/a/401/373
나는 "최상의"의 척도로 π의 연속 분수 표현에서 항의 수를 사용하기로 결정했습니다. 이 기준에 따르면 π의 가장 합리적인 근사값은 수렴입니다.
분모가 백만 미만인 π의 10 개의 수렴이 있습니다. 이것은 요청 된 167 개의 용어보다 적지 만 다른 사람들이 관심을 가질 수 있으므로 여기에 포함시킵니다.
Convergents[π, 10]
(* out *)
{3, 22/7, 333/106, 355/113, 103993/33102, 104348/33215, 208341/66317,
312689/99532, 833719/265381, 1146408/364913}
첫 번째 수렴에 대한 분모를 실제로 보려면 11 문자가 추가로 필요합니다.
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]
계속되는 분수의 형식이 일치하지 않습니다.
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++;
}
}
var
항상 친구는 아닙니다. 이를 제거하여 double
선언을 병합하고 이중 리터럴을 사용하지 않아도되고 16자를 절약 할 수 있습니다. OTOH 질문은 프로그램을 요구하므로 클래스 선언과 Main
메소드 를 추가하면 몇 가지를 잃게됩니다 .
"#{Math.PI}"
합니다.