Python - 191 octets
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]))
~ Version 4x plus rapide - 206 octets
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'entrée provient de stdin. La sortie pour n = 5000 prend environ 14 secondes avec le deuxième script (ou 60 secondes avec le premier).
Exemple d'utilisation:
$ 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 formule utilisée est la suivante:
où A n est le n ème numéro alternatif , qui peut être formellement défini comme le nombre de permutations alternées sur un ensemble de taille n (voir aussi: A000111 ). Alternativement, la séquence peut être définie comme la composition des nombres tangents et des nombres sécants ( A 2n = S n , A 2n + 1 = T n ), plus à ce sujet plus tard.
Le petit facteur de correction c n converge rapidement vers 1 lorsque n devient grand et est donné par:
Pour n = 1 , cela revient à évaluer la série Leibniz . Approximativement π à 10 ½ , le nombre de termes requis peut être calculé comme suit:
qui converge (arrondi vers le haut) à 17 , bien que des valeurs plus petites de n nécessitent beaucoup plus.
Pour le calcul de A n, il existe plusieurs algorithmes, et même une formule explicite, mais tous sont quadratiques par n . J'ai codé à l'origine une implémentation de l'algorithme de Seidel , mais elle s'avère trop lente pour être pratique. Chaque itération nécessite un terme supplémentaire pour être stocké, et les termes augmentent très rapidement en amplitude (le "mauvais" type d' O (n 2 ) ).
Le premier script utilise une implémentation d'un algorithme initialement donné par Knuth et Buckholtz :
Soit T 1, k = 1 pour tout k = 1..n
Les valeurs suivantes de T sont données par la relation de récurrence:
T n + 1, k = 1/2 [ (k - 1) T n, k-1 + (k + 1) T n, k + 1 ]
A n est alors donné par T n, 1
(voir aussi: A185414 )
Bien qu'il ne soit pas explicitement indiqué, cet algorithme calcule simultanément les nombres tangents et les nombres sécants. Le deuxième script utilise une variation de cet algorithme de Brent et Zimmermann , qui calcule T ou S , selon la parité de n . L'amélioration est quadratique de n / 2 , d'où l'amélioration de la vitesse ~ 4x.