파이 로레인 [닫힘]


52

최근 파이의 날이었던 이래로, 파이 계산을 요구 하는 여러 가지 문제발견 했습니다 .

물론 파이 로레인은 파이가 아닙니다 (제목에서 도전을 추측하면 보너스 점수 ¹ +1을 청구 할 수 있습니다). 따라서, 귀하의 작업하는 알고리즘 쓰기 또는 방법을 보이는 먼저 눈에 파이를 근사 등을 있지만 수렴하지 보장 파이쪽으로.

이는 어려운 과제이므로 간단한 테스트 사례 (예 : 10 번의 알고리즘 반복)에서 3.14 ...를 출력해야합니다. 이것은 또한 인기있는 도전이므로, 분명히하지 말고 echo(pi)IEEE 754 부동 소수점은 일부 숫자를 위 또는 아래로 반올림한다고 말하십시오.

우승자는 파이 로레인 ²을 얻습니다.

¹ 경고 : 실제로 보너스 점수는 아닙니다. 점수를 주장함으로써 2016 년 파이 데이 전에 파이를 구하기로 동의합니다.

² 경고 : 파이 로레인은 답변을 '허용됨'으로 표시 한 비유로 사용됩니다.


관련 : 링크
Sp3000

2
나는이 문제를 논제로 다루겠다고 투표하고 있습니다. meta.codegolf.stackexchange.com/a/8326/20469
cat

답변:


77

연산

잘 알려진 결과 사용 :

여기에 이미지 설명을 입력하십시오

우리는 파이썬 3에서 정의합니다 :

from math import sin
from functools import reduce
from operator import mul

def integrate(f, a, b, n):
   h = (b-a)/n
   i = h * sum(f(a+i*h+h/2) for i in range(n))
   return i

def sinc(x):
   return sin(x)/x

def borwein(n):
   def f(x):
     g = lambda i: sinc(x/(2*i+1))
     return reduce(mul, map(g, range(n)), 1)
   return f

테스팅

>>> for i in range(1,10):
...   pi = 2 * integrate(borwein(i), 0, 1000, 1000)
...   print("x[{}] = {}".format(i, pi))
x[1] = 3.140418050361841
x[2] = 3.141593078648859
x[3] = 3.1415926534611547
x[4] = 3.1415926535957164
x[5] = 3.1415926535895786
x[6] = 3.1415926535897953
x[7] = 3.1415926535897936
x[8] = 3.1415926535435896 # ???
x[9] = 3.141592616140805  # ?!!

스포일러

Borwein 적분은 실용적인 농담의 수학의 생각이다. 위의 동일성은 sinc (x / 13)까지 유지되지만 다음 값은 실제로 다음과 같습니다.

여기에 이미지 설명을 입력하십시오


12
아마도 최근에는 언더 질문에 대한 가장 좋은 대답 중 하나 일 것입니다.
Optimizer

14
"실제 농담에 대한 수학의 생각". +1
unclemeat

16
그거 좋네! 이 통합으로 잘 알려진 농담 중 하나 인 IIRC는 누군가 누군가 Wolfram Alpha에 이상한 결과를 기록하고 버그 보고서를 보냈을 때 ... WA 개발자들이 고치려고 노력했던 나이 =)
Mints97

3
이 참조 는 무슨 일이 일어나고 있는지에 대한 좋은 설명을 제공합니다.
TonioElGringo

59

파이를 찾기 위해, 우리는이 잘 알려진 미분 방정식을 통합 할 것입니다 :

> dy / dt = sin (y) * exp (t)

초기 상태

> 0 <y0 <2 * pi

이 초기 값 문제는 t가 제한없이 증가함에 따라 π로 수렴한다는 것이 잘 알려져있다. 따라서 0에서 2π 사이의 값을 합리적으로 추측하는 것만으로도 수치 적분을 수행 할 수 있습니다. 3은 π에 가까우므로 y = 3을 선택하여 시작합니다.

class PiEstimator {

    static final int numSteps = 100;
    static final double dt = 0.1, tMax = numSteps * dt;

    static double f(double y, double t){ return Math.sin(y) * Math.exp(t); }

    public static void main(String[] args){
        double y = 3;
        int n = 0;

        for(double t = 0; t < tMax; t+=dt){
            if(n%5 == 0) System.out.println(n + ": " + y);
            n++;
            y += f(y,t)*dt;
        }
    }
}

각기 다른 단계 수에 대한 결과는 다음과 같습니다.

0: 3.0
5: 3.0682513992369205
10: 3.11812938865782
15: 3.1385875952782825
20: 3.141543061526081
25: 3.141592653650948
30: 3.1415926535886047
35: 3.1415926535970526
40: 3.1415926517316737  // getting pretty close!
45: 3.1416034165087647  // uh oh
50: 2.0754887983317625  
55: 49.866227663669584
60: 64.66835482328707
65: 57.249212987256286
70: 9.980977494635624
75: 35.43035516640032
80: 51.984982646834
85: 503.8854575676292
90: 1901.3240821223753
95: 334.1514462091029
100: -1872.5333656701248

작동 방식 :

이 미분 방정식은 올바르게 적분하기가 매우 어렵 기 때문에 잘 알려져 있습니다. 작은 t 값의 경우 순진한 통합이 허용 가능한 결과를 생성하지만, t가 매우 커짐에 따라 대부분의 적분 방법은 매우 불안정합니다.


4
@UriZarfaty이 위키 백과 기사는 꽤 잘 설명합니다 : en.wikipedia.org/wiki/Stiff_equation
AJMansfield

1
무엇입니까 n? ...
Cole Johnson

1
@ AJMansfield 의미 : 그것은 어디에도 선언되지 않았습니다. 귀하의 for감속은 사용 t하지만 루프를 사용합니다 n.
Cole Johnson

1
@ColeJohnson 방금 고쳤습니다.
AJMansfield

2
미분 방정식은 dy / dt = sin (y) * exp (t)를 읽어야한다고 생각합니다.
David Zhang

6

암호:

var pi = function(m) {
  var s2 = 1, s1 = 1, s = 1;
  for (var i = 0; s >= 0; ++i) {
    s = s1 * 2 - s2 * (1 + m*m);
    s2 = s1;
    s1 = s;
  }
  return i*m*2;
};

나는 기본적으로 우연히이 시퀀스를 발견했습니다. 그것은으로 밖으로 시작 1, 1하고 그 이후 모든 용어는 s(n)주어진다 s(n) = 2*s(n - 1) - s(n - 2) * (1 + m*m). 최종 결과는 ns(n) < 0곱한 최소값 2m입니다. 으로 m작아진다, 그것은 점점 더 정확한을 얻어야한다.

pi(1/100) --> 3.14
pi(1/1000) --> 3.14
pi(1/10000) --> 3.1414
pi(1/100000) --> 3.14158
pi(1/1000000) --> 3.141452 // what?
pi(1/10000000) --> 3.1426524 // .. further away from pi

나는 이것이 1에 가까워짐에 따라 부동 소수점 오류라고 (1 + m*m)확신하지만 확실하지 않습니다. 내가 말했듯이, 우연히이 문제를 발견했습니다. 공식 이름을 잘 모르겠습니다. 와 함께이 시도하지 마십시오 m너무 작거나이 (있는 경우 영원히 실행 1 + m*m == 1으로 인해 m너무 작은 것).

누군가이 시퀀스의 이름을 알고 있거나 왜 이런 식으로 작동하는지 알고 있다면 감사하겠습니다.


나는 이것이 거의 두 숫자를 뺄 때 숫자가 손실되는 취소 때문이라고 생각합니다. S1과 s2는 반복 후에 거의 동일합니다.
Sanchises

1
나는 그것이 어떻게 작동하는지 아직 알지 못하지만, 한 번 한 일을 생각 나게합니다. 나는 잡음이 많은 신호의 누적 합계를 반복하여 0, 최대 값 1을 의미하도록 표준화했습니다. 사인파로 수렴합니다. 그 자체의 역 추출 (위상 오프셋) 신호 만 있기 때문입니다.
Sanchises

나는 math.SE에 그것을 물었고, 대답을 얻었습니다 .
Sanchises
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.