Bewerten Sie die Riemann-Zeta-Funktion bei einer komplexen Zahl

11

Einführung

Ich fand diese Frage geschlossen, weil sie unklar war, aber es war eine schöne Idee. Ich werde mein Bestes geben, um daraus eine klare Herausforderung zu machen.

Die Riemann-Zeta-Funktion ist eine spezielle Funktion, die als analytische Fortsetzung von definiert ist

Geben Sie hier die Bildbeschreibung ein

zur komplexen Ebene. Es gibt viele äquivalente Formeln dafür, was es für Code-Golf interessant macht.

Herausforderung

Schreiben Sie ein Programm, das 2 Gleitkommazahlen als Eingabe verwendet (Real- und Imaginärteil einer komplexen Zahl) und die Riemann-Zeta-Funktion an diesem Punkt auswertet.

Regeln

  • Eingabe und Ausgabe über die Konsole ODER Funktion Eingabe- und Rückgabewert
  • Eingebaute komplexe Zahlen sind nicht erlaubt, verwenden Sie Floats (Zahl, Doppel, ...)
  • Keine mathematischen Funktionen außer + - * / pow logund realwertigen Triggerfunktionen (wenn Sie integrieren möchten, verwenden Sie die Gammafunktion, ... Sie müssen diese Funktionsdefinition in den Code aufnehmen)
  • Eingabe: 2 Floats
  • Ausgang: 2 Floats
  • Ihr Code muss einen Wert enthalten, der theoretisch beliebige Genauigkeit bietet, wenn er beliebig groß / klein gemacht wird
  • Das Verhalten an Eingang 1 ist nicht wichtig (dies ist der einzige Pol dieser Funktion)

Der kürzeste Code in Bytes gewinnt!

Beispiel für Ein- und Ausgabe

Eingang:

2, 0

Ausgabe:

1.6449340668482266, 0

Eingang:

1, 1

Ausgabe:

0,5821580597520037, -0,9268485643308071

Eingang:

-1, 0

Ausgabe:

-0,08333333333333559, 0

Jens rendert
quelle
1
Was ist die erforderliche Ausgabegenauigkeit? Ich bin nicht sicher, ob ich das verstehe. Ihr Code muss einen Wert enthalten, der theoretisch beliebige Genauigkeit bietet, wenn er beliebig groß / klein gemacht wird . Meinen Sie wie ein Schleifenmaximalwert, als wenn er ohne Begrenzung erhöht wird, was die Genauigkeit erhöht? Kann dieser Wert fest codiert werden?
Luis Mendo
@DonMuesli Dies bedeutet, dass die Genauigkeit von einem Parameter abhängt, z. B. N, dem Sie einen beliebigen Wert geben können. Für eine bestimmte Genauigkeit können Sie N jedoch klein oder groß genug machen, um diese Genauigkeit zu erreichen. Das Wort ist theoretisch da, weil Sie sich keine Sorgen über die begrenzte Präzision der Maschine oder Sprache machen müssen.
Jens Renders
Zur weiteren Klärung N: genügt es , dass für jede gebunden epsund Eingabe xexistiert ein , Nwelche berechnet zeta(x)innerhalb eps; oder muss es eine geben, Ndie nur davon abhängt epsund garantiert, dass sie für eine x(oder vielleicht für xmehr als eine gegebene Funktion epsvon der Stange) die Grenze erreicht; oder kann davon Nabhängen x, aber Antworten sollten erklären, wie Ngegeben gegeben xund eps? (Meine analytische Zahlentheorie ist nicht viel, aber ich vermute, dass die Optionen 2 und 3 über alle bis auf ein oder zwei reguläre Poster hinausgehen werden).
Peter Taylor
@PeterTaylor N groß genug: Für jeden xund für jeden epsmuss ein Psolcher existieren , dass für alle N>Pdie Ausgabe näher ist als epsder genaue Wert. Ist das klar? Muss ich es für den Fall mit N klären, das klein genug ist?
Jens Renders
Nein, das ist klar genug.
Peter Taylor

Antworten:

8

Python - 385

Dies ist eine einfache Implementierung von Gleichung 21 von http://mathworld.wolfram.com/RiemannZetaFunction.html. Dabei wird die Python-Konvention für optionale Argumente verwendet. Wenn Sie eine Genauigkeit angeben möchten, können Sie der Funktion ein drittes Argument übergeben, andernfalls wird standardmäßig 1e-24 verwendet.

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)
RT
quelle
z(2,0)gibt einen falschen Wert an, sollte pi ^ 2/6 sein.
GuillaumeDufay
4

Python 3 , 303 297 Bytes

Diese Antwort basiert auf der Python-Antwort von RT mit mehreren Änderungen:

  • Zunächst Binomial(n, k)wird definiert als p = p * (n-k) / (k+1)die Veränderungen Binomial(n,k)an Binomial(n,k+1)mit jedem Durchlauf der Schleife für.
  • Zweitens (-1)**k * Binomial(n,k)wurde, p = p * (k-n) / (k+1)was das Vorzeichen bei jedem Schritt der for-Schleife umdreht.
  • Drittens wurde die whileSchleife geändert, um sofort zu überprüfen, ob a*a + b*b < E.
  • Viertens ist die bitweise nicht Operator ~wird an mehreren Stellen eingesetzt , wo sie in Golf helfen würden, mit Identitäten wie -n-1 == ~n, n+1 == -~nund n-1 == ~-n.

Einige andere kleine Modifikationen wurden vorgenommen, um das Golfen zu verbessern, z. B. das Einfügen der forSchleife in eine Zeile und das Aufrufen printeiner Zeile mit dem Code davor.

Golfvorschläge willkommen. Probieren Sie es online aus!

Bearbeiten: -6 Bytes aus einer Reihe kleiner Änderungen.

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
Sherlock9
quelle
1

Axiom, 413 315 292 Bytes

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])

Dies würde auch die Gleichung 21 von http://mathworld.wolfram.com/RiemannZetaFunction.html implementieren. Das Obige sollte die hier interpretierte Axiomfunktion z (a, b) sein, die hier 16x langsamer ist als diese unter der Funktion Zeta (a, b) [ das sollte derjenige sein, der zusammengestellt wurde] alles ungolfed und kommentiert [1 Sekunde für Zeta () gegenüber 16 Sekunden für z () für einen Wert von 20 Stellen nach dem Gleitkomma]. Für die Ziffernfrage würde man die Genauigkeit wählen, indem man Ziffern () aufruft; Funktion, zum Beispiel Ziffern (10); z (1,1) sollte 10 Ziffern nach dem Punkt drucken, aber Ziffern (50); z (1,1) sollten 50 Ziffern nach dem Punkt drucken.

-- 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)  []
RosLuP
quelle