Quiche Lorraine [chiuso]


52

Da quando è stato recentemente il Pi, ho notato una serie di sfide che ti chiedono di calcolare il pi.

Naturalmente, una quiche lorraine non è proprio una torta (puoi richiedere un punteggio bonus¹ di +1 se hai indovinato la sfida dal titolo). Pertanto, il tuo compito è quello di scrivere un algoritmo o un metodo che assomigli a Pi a prima vista, ma è garantito che non convergere verso Pi.

Questa è una sfida subdola, quindi assicurati che produrrà 3.14 ... per un semplice caso di test, ad esempio con 10 iterazioni del tuo algoritmo. Questa è anche una sfida di popolarità, quindi non andare per l'ovvio echo(pi)e dire che il punto in virgola mobile IEEE 754 arrotonda alcune cifre su o giù.

Il vincitore riceve una quiche lorraine².

¹ Avvertenza: in realtà non è un punteggio bonus. Rivendicando il punteggio, accetti di prepararmi una torta prima di Pi Day, 2016

² Attenzione: la quiche lorraine viene utilizzata come metafora per avere la risposta contrassegnata come "accettata"


Correlati: link
Sp3000

2
Sto votando per chiudere questa domanda come fuori tema perché le sfide subdole non sono più in tema qui. meta.codegolf.stackexchange.com/a/8326/20469
cat

Risposte:


77

Algoritmo

Utilizzando il noto risultato:

inserisci qui la descrizione dell'immagine

definiamo in 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

analisi

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

spoiler

L' integrale di Borwein è l'idea matematica di uno scherzo pratico. Mentre l'identità sopra regge fino a sinc (x / 13), il valore successivo è in realtà:

inserisci qui la descrizione dell'immagine


12
Probabilmente una delle migliori risposte a una domanda subdola negli ultimi tempi.
Ottimizzatore

14
"l'idea matematica di uno scherzo pratico". +1
carne di zio

16
Bella questa! IIRC, una delle battute più conosciute con questo integrale è stato quando qualcuno ha registrato i risultati fino allo strano su Wolfram Alpha e ha inviato un bug report ... Che gli sviluppatori di WA hanno trascorso anni cercando di risolvere =)
Mints97

3
Questo riferimento fornisce una buona spiegazione di ciò che sta succedendo.
TonioElGringo,

59

Per trovare pi, integreremo questa ben nota equazione differenziale:

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

Con una condizione iniziale

> 0 <y0 <2 * pi

È noto che questo problema del valore iniziale converge in π quando t aumenta senza limite. Quindi, tutto ciò di cui abbiamo bisogno è iniziare con un'ipotesi ragionevole per qualcosa tra 0 e 2π, e possiamo eseguire l'integrazione numerica. 3 è vicino a π, quindi sceglieremo y = 3 per iniziare.

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

Ecco alcuni risultati per ciascuno per diversi numeri di passaggi:

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

Come funziona:

Tale equazione differenziale è ben nota perché è estremamente difficile da integrare correttamente. Mentre per piccoli valori di t un'integrazione ingenua produrrà risultati accettabili, la maggior parte dei metodi di integrazione mostra un'estrema instabilità quando t diventa molto grande.


4
@UriZarfaty Questo articolo di Wikipedia lo spiega abbastanza bene: en.wikipedia.org/wiki/Stiff_equation
AJMansfield

1
Che cos'è n? ...
Cole Johnson,

1
@AJMansfield intendevo: non è stato dichiarato da nessuna parte. La tua fordecelerazione usa t, ma usa il tuo loop n.
Cole Johnson,

1
@ColeJohnson L'ho appena risolto.
AJMansfield,

2
Penso che la tua equazione differenziale dovrebbe leggere dy / dt = sin (y) * exp (t).
David Zhang,

6

Codice:

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

Fondamentalmente ho scoperto questa sequenza per caso. Inizia come 1, 1e ogni termine successivo s(n)è dato da s(n) = 2*s(n - 1) - s(n - 2) * (1 + m*m). Il risultato finale è il più piccolo ntale che s(n) < 0moltiplicato per 2m. Man mano che msi riduce, dovrebbe diventare sempre più preciso.

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

Sono abbastanza sicuro che si tratti di errori in virgola mobile man mano che ci (1 + m*m)si avvicina a uno, ma non ne sono sicuro. Come ho detto, mi sono imbattuto in questo per caso. Non sono sicuro del suo nome ufficiale. Non provarlo con un valore mtroppo piccolo o funzionerà per sempre (se 1 + m*m == 1dovuto al mfatto che è così piccolo).

Se qualcuno conosce il nome di questa sequenza o perché si comporta in questo modo, lo apprezzerei.


Penso che ciò sia dovuto alla cancellazione, che è una perdita di cifre quando si sottraggono due numeri quasi uguali. S1 e s2 sono quasi uguali dopo un'iterazione.
Sanchises,

1
Devo ancora scoprire come funziona, ma mi ricorda qualcosa che ho fatto una volta: ho preso ripetutamente la somma cumulativa di un segnale rumoroso e l'ho normalizzato per significare 0, valore massimo 1. Ciò converrebbe in un'onda sinusoidale, dal momento che è l'unico segnale che è il suo proprio anti-derivato (con un offset di fase).
Sanchises,

L'ho chiesto a math.SE e ho ottenuto questa risposta.
Sanchises,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.