Valuta la funzione Zeta di Riemann su un numero complesso


11

introduzione

Ho trovato questa domanda che era chiusa perché non era chiara, ma era una bella idea. Farò del mio meglio per renderlo una chiara sfida.

La funzione di Riemann Zeta è una funzione speciale definita come la continuazione analitica di

inserisci qui la descrizione dell'immagine

al piano complesso. Ci sono molte formule equivalenti per questo che lo rendono interessante per il golf del codice.

Sfida

Scrivi un programma che accetta 2 float come input (la parte reale e immaginaria di un numero complesso) e valuta la funzione di Riemann Zeta a quel punto.

Regole

  • Input e output via console OPPURE input e valore di ritorno
  • I numeri complessi incorporati non sono ammessi, usare i float (numero, doppio, ...)
  • Nessuna funzione matematica eccetto + - * / pow loge funzioni trig con valore reale (se si desidera integrare, utilizzare la funzione gamma, ... è necessario includere questa definizione di funzioni nel codice)
  • Ingresso: 2 galleggianti
  • Uscita: 2 galleggianti
  • Il tuo codice deve contenere un valore che dia una precisione teoricamente arbitraria quando reso arbitrario grande / piccolo
  • Il comportamento all'ingresso 1 non è importante (questo è l'unico polo di questa funzione)

Vince il codice più corto in byte!

Esempio di input e output

Ingresso:

2, 0

Produzione:

1.6449340668482266, 0

Ingresso:

1, 1

Produzione:

0,5821580597520037, -0,9268485643308071

Ingresso:

-1, 0

Produzione:

-0.08333333333333559, 0


1
Qual è la precisione di uscita richiesta? Non sono sicuro di capire che il tuo codice deve contenere un valore che dia teoricamente precisione arbitraria quando reso arbitrario grande / piccolo . Vuoi dire come un valore massimo di loop rispetto a quando aumentato senza limite dà maggiore precisione? Quel valore può essere codificato?
Luis Mendo,

@DonMuesli Ciò significa che la precisione dipende da un parametro, ad esempio N, che puoi dare a qualsiasi valore ti piaccia, ma per qualsiasi precisione data, puoi rendere N abbastanza piccolo o grande per raggiungere quella precisione. La parola teoricamente è lì perché non devi preoccuparti della precisione limitata della macchina o del linguaggio.
Jens Renders

Per chiarire ulteriormente N: è sufficiente che per ogni limite epse input xesista un Nche calcola zeta(x)all'interno eps; o deve esistere un Nche dipende solo da epse garantisce che per qualsiasi x(o forse per qualcosa di xpiù di una data funzione epsdal polo) raggiunge il limite; o può Ndipendere da x, ma le risposte dovrebbero spiegare come calcolare Ndato xe eps? (La mia teoria analitica dei numeri non è molto, ma sospetto che le opzioni 2 e 3 andranno oltre tutti i poster tranne uno o due).
Peter Taylor,

@PeterTaylor N abbastanza grande: per qualsiasi xe per qualsiasi epsdeve esistere un Ptale che per tutto N>Pl'output è più vicino epsal valore esatto. È chiaro? Devo chiarirlo per il caso con N abbastanza piccolo?
Jens Renders

No, è abbastanza chiaro.
Peter Taylor,

Risposte:


8

Python - 385

Questa è un'implementazione semplice dell'equazione 21 da http://mathworld.wolfram.com/RiemannZetaFunction.html Questo usa la convenzione di Python per argomenti opzionali; se si desidera specificare una precisione, è possibile passare un terzo argomento alla funzione, altrimenti utilizza 1e-24 per impostazione predefinita.

import numpy as N
def z(r,i,E=1e-24):
 R=0;I=0;n=0;
 while(True):
  a=0;b=0;m=2**(-n-1)
  for k in range(0,n+1):
   M=(-1)**k*N.product([x/(x-(n-k))for x in range(n-k+1,n+1)]);A=(k+1)**-r;t=-i*N.log(k+1);a+=M*A*N.cos(t);b+=M*A*N.sin(t)
  a*=m;b*=m;R+=a;I+=b;n+=1
  if a*a+b*b<E:break
 A=2**(1-r);t=-i*N.log(2);a=1-A*N.cos(t);b=-A*N.sin(t);d=a*a+b*b;a=a/d;b=-b/d
 print(R*a-I*b,R*b+I*a)

z(2,0)fornisce un valore errato, dovrebbe essere pi ^ 2/6.
Guillaume

4

Python 3 , 303 297 byte

Questa risposta si basa sulla risposta Python di RT con diverse modifiche:

  • Innanzitutto, Binomial(n, k)viene definito come il p = p * (n-k) / (k+1)quale cambia Binomial(n,k)ad Binomial(n,k+1)ogni passaggio del ciclo for.
  • In secondo luogo, è (-1)**k * Binomial(n,k)diventato quello p = p * (k-n) / (k+1)che lancia il segno ad ogni passo del ciclo for.
  • In terzo luogo, il whileloop è stato modificato per verificare immediatamente se a*a + b*b < E.
  • In quarto luogo, il bit a bit senza operatore ~viene utilizzato in diversi luoghi dove sarebbero di aiuto nel golf, utilizzando le identità, come -n-1 == ~n, n+1 == -~ne n-1 == ~-n.

Diverse altre piccole modifiche sono state apportate per migliorare il golf, come mettere il forloop su una linea e la chiamata printsu una linea con il codice precedente.

Suggerimenti di golf benvenuti. Provalo online!

Modifica: -6 byte da una serie di piccole modifiche.

import math as N
def z(r,i,E=1e-40):
 R=I=n=0;a=b=1
 while a*a+b*b>E:
  a=b=0;p=1;m=2**~n
  for k in range(1,n+2):M=p/k**r;p*=(k-1-n)/k;t=-i*N.log(k);a+=M*N.cos(t);b+=M*N.sin(t)
  a*=m;b*=m;R+=a;I+=b;n+=1
 A=2**-~-r;t=-i*N.log(2);x=1-A*N.cos(t);y=A*N.sin(t);d=x*x+y*y;return(R*x-I*y)/d,(R*y+I*x)/d

1

Axiom, 413 315 292 byte

p(n,a,b)==(x:=log(n^b);y:=n^a;[y*cos(x),y*sin(x)]);z(a,b)==(r:=[0.,0.];e:=10^-digits();t:=p(2,1-a,-b);y:=(1-t.1)^2+t.2^2;y=0=>[];m:=(1-t.1)/y;q:=t.2/y;n:=0;repeat(w:=2^(-n-1);abs(w)<e=>break;r:=r+w*reduce(+,[(-1)^k*binomial(n,k)*p(k+1,-a,-b) for k in 0..n]);n:=n+1);[r.1*m-q*r.2,m*r.2+r.1*q])

Questo implementerebbe anche l'equazione 21 di http://mathworld.wolfram.com/RiemannZetaFunction.html Quanto sopra dovrebbe essere quello che ha interpretato la funzione Axiom z (a, b) qui 16 volte più lenta di questa funzione Zeta (a, b) [ quello dovrebbe essere quello compilato] tutto non salvato e commentato [1 secondo per Zeta () contro 16 secondi per z () per un valore di 20 cifre dopo il punto float]. Per la domanda sulle cifre, si sceglierebbe la precisione chiamando digit (); funzione, ad esempio cifre (10); z (1,1) dovrebbe stampare 10 cifre dopo il punto, ma le cifre (50); z (1,1) dovrebbero stampare 50 cifre dopo il punto.

-- elevImm(n,a,b)=n^(a+i*b)=r+i*v=[r,v]
elevImm(n:INT,a:Float,b:Float):Vector Float==(x:=log(n^b);y:=n^a;[y*cos(x),y*sin(x)]::Vector Float);

--                      +oo               n
--                      ---              ---
--             1        \       1        \            n 
--zeta(s)= ---------- * /     ------  *  /    (-1)^k(   )(k+1)^(-s)
--          1-2^(1-s)   ---n  2^(n+1)    ---k         k  
--                       0                0


Zeta(a:Float,b:Float):List Float==
  r:Vector Float:=[0.,0.]; e:=10^-digits()

  -- 1/(1-2^(1-s))=1/(1-x-i*y)=(1-x+iy)/((1-x)^2+y^2)=(1-x)/((1-x)^2+y^2)+i*y/((1-x)^2+y^2)    

  t:=elevImm(2,1-a,-b);
  y:=(1-t.1)^2+t.2^2;
  y=0=>[] 
  m:=(1-t.1)/y; 
  q:=t.2/y
  n:=0
  repeat
     w:=2^(-n-1)
     abs(w)<e=>break  --- this always terminate because n increase
     r:=r+w*reduce(+,[(-1)^k*binomial(n,k)*elevImm(k+1,-a,-b) for k in 0..n])
     n:=n+1
  -- (m+iq)(r1+ir2)=(m*r1-q*r2)+i(m*r2+q*r1)
  [r.1*m-q*r.2,m*r.2+r.1*q]

this is one test for the z(a,b) function above:

(10) -> z(2,0)
   (10)  [1.6449340668 482264365,0.0]
                                              Type: List Expression Float
(11) -> z(1,1)
   (11)  [0.5821580597 520036482,- 0.9268485643 3080707654]
                                              Type: List Expression Float
(12) -> z(-1,0)
   (12)  [- 0.0833333333 3333333333 3,0.0]
                                              Type: List Expression Float
(13) -> z(1,0)
   (13)  []
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.