Calcolo delle cifre troncate somme di poteri di pi


12

Dato un numero intero positivo n , la somma delle prime n cifre decimali della parte frazionaria di π n .

Esempio di input e output:

1 → 1
2 → 14
3 → 6
4 → 13
5 → 24
50 → 211
500 → 2305
5000 → 22852

Le funzioni integrate che calcolano cifre di π o valutano serie di potenze o frazioni continue non sono consentite. Si applicano scappatoie standard . L'input / output può essere in un formato conveniente (stdin, stdout, funzione in / output, ecc.).

Vince il codice più breve in byte .


Sono vietate anche altre funzioni di trigger che potrebbero essere utilizzate per calcolare pi, ma non necessariamente direttamente, come logaritmi arctangenti o immaginari? Inoltre, esiste un limite superiore ad n che può fallire dopo?
FryAmTheEggman,

@FryAmTheEggman Se quelle funzioni di trigger possono calcolare cifre arbitrarie di pi, allora sì sono bandite. Il tuo programma dovrebbe funzionare in teoria per qualsiasi n , ma è perdonato se il tempo di esecuzione o la memoria diventano troppo alti.
orlp,

Risposte:


4

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.


1
Ottima spiegazione dei calcoli alla base della tua risposta.
Logic Knight

3

Python 2, 246 byte

Ho adottato un approccio simile alla mia risposta in Calculate π con convergenza quadratica . L'ultima riga prende l'ennesima potenza di pi e somma le cifre. Il test N = 5000 richiede circa un minuto.

from decimal import*
d=Decimal
N=input()
getcontext().prec=2*N
j=d(1)
h=d(2)
f=h*h
g=j/h
a=j
b=j/h.sqrt()
t=j/f
p=j
for i in bin(N)[2:]:e=a;a,b=(a+b)/h,(a*b).sqrt();c=e-a;t-=c*c*p;p+=p
k=a+b
l=k*k/f/t
print sum(map(int,`l**N`.split('.')[1][:N]))

Alcuni test:

$ echo 1 | python soln.py
1
$ echo 3 | python soln.py
6
$ echo 5 | python soln.py
24
$ echo 500 | python soln.py
2305
$ echo 5000 | python soln.py
22852

Il codice ungolfed:

from decimal import *
d = Decimal

N = input()
getcontext().prec = 2 * N

# constants:
one = d(1)
two = d(2)
four = two*two
half = one/two

# initialise:
a = one
b = one / two.sqrt()
t = one / four
p = one

for i in bin(N)[2:] :
    temp = a;
    a, b = (a+b)/two, (a*b).sqrt();
    pterm = temp-a;
    t -= pterm*pterm * p;
    p += p

ab = a+b
pi = ab*ab / four / t
print sum(map(int, `pi ** N`.split('.')[1][:N]))

Linea 8, puoi girare a=je p=jandare in a=p=jiirc. Può essere.
Elias Benevedes,

Grazie. Esistono ulteriori ottimizzazioni del golf per questo codice, ma non sarà competitivo senza una riscrittura usando un algoritmo senza decimale.
Logic Knight

1

Pyth, 33

s<>j^u+/*GHhyHy^TyQr*TQ0ZQT_y*QQQ

Sulla base di questa risposta di isaacg . Probabilmente potrebbe essere più giocato a golf. Lento.

s<>j            Digit sum of...
  ^                 
    u               Evaluate pi = 2 + 1/3*(2 + 2/5*(2 + 3/7*(2 + 4/9*(2 + ...))))
      +
        /
          *GH
          hyH
        y^TyQ       Except we generate a large integer containing 2n digits,
                    rather than a fraction.
      r*TQ0         Experimentally verified that 10*n iterations will give enough
                    precision for 2n digits (# digits correct grows faster than 2n).
      Z
    Q               To the nth power.
  T_y*QQQ         Get the last 2n^2 digits (all the fractional digits) and get the
                  first n fractional digits.

1
Questa risposta richiede davvero almeno una spiegazione sufficiente per giustificare che calcola cifre sufficienti per ottenere la risposta giusta.
Peter Taylor,

@PeterTaylor Aggiungerò una spiegazione domani, sto per andare a letto.
orlp

Ogni iterazione produce un bit corretto (vedi Appendice A ). Le cifre da 2n dovrebbero richiedere ~ 6.64n iterazioni.
primo
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.