Python - 191 bajtów
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]))
~ 4x szybsza wersja - 206 bajtów
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]))
Dane wejściowe są pobierane ze standardowego wejścia. Wyjście dla n = 5000 zajmuje około 14s przy drugim skrypcie (lub 60s przy pierwszym).
Przykładowe użycie:
$ 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
Zastosowana formuła jest następująca:
gdzie A n jest n- tą liczbą naprzemienną , którą można formalnie zdefiniować jako liczbę naprzemiennych permutacji w zbiorze wielkości n (patrz także: A000111 ). Alternatywnie sekwencja może być zdefiniowana jako kompozycja o numerach styczna siecznej liczb ( 2n = S n , 2n + 1 = T n ), o tym później.
Mały współczynnik korygujący c n szybko zbliża się do 1, gdy n staje się duży i jest określony przez:
Dla n = 1 oznacza to ocenę serii Leibniza . Zbliżenie π jako 10 pół liczba wymaganych warunków może być obliczona jako:
co zbiega się (w zaokrągleniu w górę) do 17 , chociaż mniejsze wartości n wymagają znacznie więcej.
Do obliczenia A n istnieje kilka algorytmów, a nawet wyraźna formuła, ale wszystkie są kwadratowe według n . Pierwotnie kodowałem implementację algorytmu Seidela , ale okazuje się on zbyt wolny, aby był praktyczny. Każda iteracja wymaga zapisania dodatkowego terminu, a jego terminy bardzo szybko rosną („zły” rodzaj O (n 2 ) ).
Pierwszy skrypt wykorzystuje implementację algorytmu pierwotnie podanego przez Knutha i Buckholtza :
Niech T 1, k = 1 dla wszystkich k = 1..n
Kolejne wartości T są podane przez relację powtarzalności:
T n + 1, k = 1/2 [ (k - 1) T n, k-1 + (k + 1) T n, k + 1 ]
N jest wstrzykiwany przez T n, 1
(patrz także: A185414 )
Chociaż nie jest to wyraźnie określone, algorytm oblicza jednocześnie zarówno Liczby Styczne, jak i Liczby Secant. Drugi skrypt wykorzystuje odmianę tego algorytmu autorstwa Brenta i Zimmermanna , która oblicza T lub S , w zależności od parzystości n . Poprawa jest kwadratowa o n / 2 , stąd poprawa prędkości ~ 4x.