Python - 191 byte
t=i=1L;k=n=input();f=2000*20**n;A=range(n+1)
for k in range(2,n):A=[(A[j-1]+A[j+1])*j>>1for j in range(n-k+1)];f*=k
while k:k=(1-~i*n%4)*f/A[1]/i**n;t+=k;i+=2
print sum(map(int,`t`[-n-4:-4]))
~ 4 volte più veloce - 206 byte
t=i=1L;k=n=input();f=2000*20**n;A=[0,1]+[0]*n
for k in range(1,n):
f*=k
for j in range(-~n/2-k+1):A[j]=j*A[j-1]+A[j+1]*(j+2-n%2)
while k:k=(1-~i*n%4)*f/A[1]/i**n;t+=k;i+=2
print sum(map(int,`t`[-n-4:-4]))
L'input è preso dallo stdin. L'output per n = 5000 richiede circa 14 secondi con il secondo script (o 60 secondi con il primo).
Esempio di utilizzo:
$ echo 1 | python pi-trunc.py
1
$ echo 2 | python pi-trunc.py
14
$ echo 3 | python pi-trunc.py
6
$ echo 4 | python pi-trunc.py
13
$ echo 5 | python pi-trunc.py
24
$ echo 50 | python pi-trunc.py
211
$ echo 500 | python pi-trunc.py
2305
$ echo 5000 | python pi-trunc.py
22852
La formula utilizzata è la seguente:
dove A n è il n ° alternata numero , che può essere formalmente definito come il numero di permutazione alternata su un insieme di dimensione n (vedi anche: A000111 ). In alternativa, la sequenza può essere definita come la composizione dei Numeri Tangenti e Numeri Secanti ( A 2n = S n , A 2n + 1 = T n ), più avanti in seguito.
Il piccolo fattore di correzione c n converge rapidamente a 1 quando n diventa grande ed è dato da:
Per n = 1 , ciò equivale a valutare la serie Leibniz . Approssimando π come 10 ½ , il numero di termini richiesti può essere calcolato come:
che converge (arrotondando per eccesso) a 17 , anche se i valori più piccoli di n richiedono molto di più.
Per il calcolo di A n ci sono diversi algoritmi e persino una formula esplicita, ma tutti sono quadratici di n . Inizialmente ho codificato un'implementazione dell'algoritmo di Seidel , ma diventa troppo lento per essere pratico. Ogni iterazione richiede che venga memorizzato un termine aggiuntivo e che i termini aumentino molto rapidamente (il tipo "errato" di O (n 2 ) ).
Il primo script utilizza un'implementazione di un algoritmo originariamente fornito da Knuth e Buckholtz :
Sia T 1, k = 1 per tutti k = 1..n
I valori successivi di T sono dati dalla relazione di ricorrenza:
T n + 1, k = 1/2 [ (k - 1) T n, k-1 + (k + 1) T n, k + 1 ]
A n è quindi dato da T n, 1
(vedi anche: A185414 )
Sebbene non sia esplicitamente dichiarato, questo algoritmo calcola contemporaneamente sia i Numeri Tangenti sia i Numeri Secanti. Il secondo script utilizza una variante di questo algoritmo di Brent e Zimmermann , che calcola T o S , a seconda della parità di n . Il miglioramento è quadratico di n / 2 , quindi il miglioramento della velocità ~ 4x.