Kiş Lorraine [kapalı]


52

Yakın zamanda Pi gündü beri var fark bir dizi ait zorlukları pi hesaplamak istiyoruz.

Tabii ki, bir kiş lorraine tam bir pasta değildir (unvanın zorluğunu tahmin ederseniz +1 Bonus Puan¹ talep edebilirsiniz). Aynı şekilde, iş etmektir bir algoritma yazmak veya yöntemini görünüyor ilk bakışta Pi yaklaşır gibi, ancak yakınsama için garanti Pi doğru.

Bu, aldatılmış bir zorluktur, bu nedenle basit bir test durumu için 3.14 ... çıkacağına emin olun, örneğin algoritmanızın 10 tekrarlaması. Bu aynı zamanda bir popülerlik mücadelesidir, bu yüzden bariz bir şey echo(pi)söyleme ve IEEE 754 kayan noktaların bazı basamakları aşağı veya yukarı yuvarladığını söyleme.

Kazanan bir kiş lorraine² alır.

¹ Uyarı: aslında bir bonus puanı değil. Skoru talep ederek, Pi Day, 2016'dan önce bana bir turta pişirmeyi kabul edersiniz.

² Uyarı: Kiş Loris, cevabınızı 'kabul edildi' olarak işaretlemek için bir metafor olarak kullanılır.



2
Bu soruyu konu dışı olarak kapatmak için oy veriyorum, çünkü asıl zorluklar artık burada konu dışı değil. meta.codegolf.stackexchange.com/a/8326/20469
kedi

Yanıtlar:


77

Algoritma

İyi bilinen sonucu kullanarak:

görüntü tanımını buraya girin

Python 3'te tanımlarız:

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

Test yapmak

>>> 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  # ?!!

Bir şeyin önceden reklamı

Borwein integrali pratik şaka math fikri. Yukarıdaki kimlik sinc (x / 13) 'e dayanırken, bir sonraki değer aslında:

görüntü tanımını buraya girin


12
Muhtemelen son zamanlarda bir asıl soruya en iyi cevaplardan biri.
Doktor

14
"matematik şakası fikri". +1
unclemeat

16
Bu iyi bir tanesi! Birisi Wolfram Alpha üzerinde garip birine kadar sonuçları kaydedildi ve) = düzeltmeye çalışırken WA Devs yaş geçirdi bir hata raporu ... gönderildiğinde IIRC, bu integrali ile daha iyi bilinen şakalarından biri oldu
Mints97

3
Bu referans , neler olup bittiğinin iyi bir açıklamasını verir.
TonioElGringo

59

Pi'yi bulmak için, bu iyi bilinen diferansiyel denklemi birleştireceğiz:

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

İlk şartla

> 0 <y0 <2 * pi

Bu başlangıç ​​değer probleminin, sınırlanmadıkça arttıkça π 'ya yaklaştığı iyi bilinmektedir. Böylece, ihtiyacımız olan tek şey 0 ile 2π arasında bir şey için makul bir tahminle başlamaktır ve sayısal entegrasyon yapabiliriz. 3 π 'ya yakın, bu yüzden başlamak için y = 3 seçeceğiz.

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;
        }
    }
}

Aşağıda, her adımda farklı adımlar için sonuçlar verilmiştir:

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

Nasıl çalışır:

Bu diferansiyel denklem iyi bilinmektedir, çünkü doğru şekilde entegrasyonu son derece zordur. Küçük t değerleri için naif entegrasyon kabul edilebilir sonuçlar üretse de, çoğu entegrasyon metodu t çok büyüdükçe aşırı kararsızlık sergiler.


4
@UriZarfaty Bu wikipedia makalesi oldukça iyi açıklar: en.wikipedia.org/wiki/Stiff_equation
AJMansfield 19:15

1
Nedir n? ...
Cole Johnson

1
@ AJMansfield Demek istediğim: hiçbir yerde ilan edilmedi. Sizin foryavaşlama kullanır t, ancak döngü kullanır n.
Cole Johnson,

1
@ColeJohnson Daha yeni tamir ettim.
AJMansfield

2
Bence sizin diferansiyel denkleminiz dy / dt = sin (y) * exp (t) olmalı.
David Zhang,

6

Kod:

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;
};

Temel olarak bu sırayı kazara keşfettim. 1, 1Her bir terim olarak verilir ve bundan sonra s(n)verilir s(n) = 2*s(n - 1) - s(n - 2) * (1 + m*m). Sonuçta en küçük nolacak şekilde s(n) < 0çarpılır 2m. Gibi mküçülür, daha ve daha doğru almalısınız.

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

Bunların birbirine (1 + m*m)yaklaşırken kayan nokta hataları olduğundan eminim ama emin değilim. Dediğim gibi, kazara bunun üzerine tökezledim. Resmi isminden emin değilim. Bir ile bu kalkmayın mçok küçük ya da (eğer sonsuza çalışacak 1 + m*m == 1dolayı mkadar küçük olmak).

Bu dizinin adını veya neden böyle davrandığını bilen biri varsa, minnettar olurum.


Bunun, neredeyse eşit sayıdaki iki sayının çıkarılmasında sayı kaybı olan iptal nedeniyle olduğunu düşünüyorum. S1 ve s2, bir yinelemeden sonra neredeyse eşittir.
Sanchises,

1
Nasıl çalıştığını henüz anlayamadım, ama bana bir zamanlar yaptığım bir şeyi hatırlatıyor: Tekrar tekrar gürültülü bir sinyalin toplamını aldım ve 0, maksimum değer 1 anlamına geldiğini normalleştirdim. Zira kendi anti-türevi olan tek sinyal budur (faz kayması ile).
Sanchises,

Ben matematikte sordum.SE ve bu cevabı aldım .
Ocak'ta
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.