キッシュロレーヌ[閉店]


52

最近はPiの日だったので、piを計算するように要求する多く課題に気付きました。

もちろん、キッシュロレーヌは単なるパイではありません(タイトルからチャレンジを推測した場合、+ 1のボーナススコア¹を請求できます)。そのように、あなたの仕事をすることであるアルゴリズムの書き込み方法をことルックスことなどが一目見ただけでパイを近似しているが、ない収束することが保証さ Piを向けました。

これは手に負えない課題なので、たとえば、アルゴリズムを10回繰り返して、簡単なテストケースで3.14 ...を出力するようにしてください。これは人気の課題でもあるため、echo(pi)IEEE 754浮動小数点は一部の桁を切り上げまたは切り捨てると言うのは明白です。

勝者はキッシュlorraine²を獲得します。

¹警告:実際にはボーナススコアではありません。スコアを請求することにより、2016年のPi Dayの前にパイを焼くことに同意したことになります

² 警告:キッシュロレーヌは、回答を「承認済み」としてマークするための隠metaとして使用されます


関連:リンク
Sp3000

2
ここでは、手に負えない課題がトピックではなくなったため、この質問をトピック外として終了することに投票しています。meta.codegolf.stackexchange.com/a/8326/20469
cat

回答:


77

アルゴリズム

既知の結果を使用する:

ここに画像の説明を入力してください

Python 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積分は悪ふざけの数学の考え方です。上記のIDはsinc(x / 13)まで保持されますが、次の値は実際には次のとおりです。

ここに画像の説明を入力してください


12
おそらく、最近の手に負えない質問に対する最良の答えの1つです。
オプティマイザー

14
「数学の実用的な冗談のアイデア」。+1
非破壊

16
それは良いものです!IIRC、この一体型で、よりよく知られたジョークの一つは、誰かがウルフラムアルファの奇妙な1までの結果を記録したときだった、と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このWikipediaの記事はかなりよく、それを説明する:en.wikipedia.org/wiki/Stiff_equation
AJMansfield

1
何ですn?...
コール・ジョンソン

1
@AJMansfield私が言ったのは、どこにも宣言されていないということです。あなたのfor減速の用途tが、あなたのループの使用n
コールジョンソン

1
@ColeJohnson修正しました。
-AJMansfield

2
あなたの微分方程式はdy / dt = sin(y)* exp(t)と読むべきだと思います。
デビッドチャン

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 + m*m)1に近づくにつれて浮動小数点エラーであることをかなり確信していますが、私にはわかりません。私が言ったように、私は偶然これにつまずいた。正式名称は定かではありません。でこれをしようとしないでくださいm小さすぎるか、それは(もし永遠に実行されます1 + m*m == 1のためにm非常に小さいこと)。

誰かがこのシーケンスの名前を知っているか、なぜこのように動作するのかを知っているなら、私はそれを感謝します。


これはキャンセルによるものだと思います。これは、ほぼ等しい2つの数字を差し引くと桁が失われることです。S1とs2は、反復後にほぼ等しくなります。
-Sanchises

1
どのように機能するかはまだわかりませんが、一度やったことを思い出させます:ノイズの多い信号の累積合計を繰り返し、0、最大値1を意味するように正規化しました。これは正弦波に収束し、それはそれ自身の反微分である唯一の信号であるためです(位相オフセットあり)。
-Sanchises

math.SEでそれを尋ねたところ、この答えが得られました。
-Sanchises
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.