Entwickler-Ecke

Off Topic - Riemannsche Zeta-Funktion


Mathematiker - Mo 15.04.13 10:48
Titel: Riemannsche Zeta-Funktion
Hallo,
zur Ablenkung von dem Moser-Problem http://www.entwickler-ecke.de/viewtopic.php?t=111412 wollte ich die tolle Grafik
riemann
aus dem genialen Buch "Bilder der Mathematik" von Glaeser und Polthier mit Delphi erstellen.
Dargestellt wird der Verlauf der Riemannschen Zetafunktion für Zeta(0,5 + i t) in Abhängigkeit von t. Nach 3 Stunden erhielt ich aber immer noch etwas ganz anderes, bis ich merkte, dass ich keine Ahnung von dieser Mathematik habe.
Meine Berechnung über die Summe 1 + 1/2^z + 1/3^z + ... funktioniert nur für Realteile größer 1, d.h. alle Mühe war umsonst. :bawling:

Meine Frage nun: Kennt jemand von Euch eine Möglichkeit die Zeta-Funktion auch für 0,5 + i t effektiv und schnell zu berechnen. Aus den diversen Beschreibungen im Netz, u.a. bei Wikipedia, werde ich nicht schlau.

Ich weiß, dass die Frage eigentlich nichts hier in der EE zu suchen hat (deshalb Off-Topic), aber im Mathe-Forum werde ich fast wie ein "Aussätziger" :hair: behandelt. Wie kann ich "richtige" Mathematiker auch nach einer numerischen(!) Berechnung fragen. :autsch:
Vielen Dank für evtl. Hilfe.

Beste Grüße
("falscher") Mathematiker

Wichtiger Nachtrag:
Auf Euch hier ist immer Verlass! Danke!
Dank user profile iconGammatesters Hinweisen habe ich die Berechnung hinbekommen und damit das erste kleinere Programm, dass eine ähnliche Grafik erzeugt.
Rev 1: zusätzlich mit Darstellung im ebenen Koordinatensystem
Rev 2: mit Nullstellenberechnung
Rev 3: Erweiterung auf 2. und 3.Restglied, womit die Nullstellen auf 3 Dezimalstellen genau sind
Rev 4: die von user profile iconGammatester wesentlich verbesserte Berechnung ist eingebaut und damit deutlich schneller und genauer.


Horst_H - Mo 15.04.13 12:23

Hallo,

Du kennst Dich ja als Mathematiker mit solchen Formeln aus:
http://de.wikipedia.org/wiki/Riemannsche_ζ-Funktion#Reihenentwicklungen

Gruß Horst


Gammatester - Mo 15.04.13 12:24

Du willst wohl nur Zeta(1/2 + i t) für reelle t haben. Dazu habe ich auch die Schnelle folgende Hinweise:

Pughs Masterarbeit hat C-Sourcen im Anhang auch für Nicht-Multiprazisions-Rechnungen: G.R. Pugh, The Riemann-Siegel formula and large scale computations of the Riemann zeta function http://web.viu.ca/pughg/thesis.d/masters.thesis.ps.

Siehe auch Ken Takusagawa's Seite Tabulating values of the Riemann-Siegel Z function along the critical line: http://web.mit.edu/kenta/www/six/parallel/2-Final-Report.html.

Außerdem gibt's noch einen Hinweis in Crandall/Pomerance (das und ev. weitere Source-Quellen kann ich aber erst heute Abend zu Hause checken).

Gruß Gammatester


Tranx - Mo 15.04.13 12:26

user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:
Ich weiß, dass die Frage eigentlich nichts hier in der EE zu suchen hat (deshalb Off-Topic), aber im Mathe-Forum werde ich fast wie ein "Aussätziger" :hair: behandelt. Wie kann ich "richtige" Mathematiker auch nach einer numerischen(!) Berechnung fragen. :autsch:
Vielen Dank für evtl. Hilfe.

Beste Grüße
("falscher") Mathematiker


Idioten, sage ich nur. Die Mathematik wäre nie was geworden, wenn nicht Anwendugnen (Pyramidenbau, Tempelbau ...) dahinter gestanden hätte. Viele Mathematiker haben anwendungsorientiert gearbeitet (Archimedes und a.).

Also ist es wie immer im Leben, die Falschen sind immer auf der falschen Seite ;) Interessantes Problem. Mal sehen, ob ich es mit meinen noch geringeren Mathekenntnissen überhaupt raffe.

Gruß Gunther


Martok - Mo 15.04.13 14:06

Im Zweifelsfall hilft immer der Herr Weisstein [http://mathworld.wolfram.com/RiemannZetaFunction.html] als Meta-Quelle... wobei ich das nicht mal annähernd versucht hab zu verstehen. Keine Ahnung was da steht :mrgreen:


Mathematiker - Mo 15.04.13 14:25

Hallo,
und Danke für alle Hinweise.

Dank user profile iconGammatester habe ich den Text http://web.mit.edu/kenta/www/six/parallel/2-Final-Report.html einigermaßen verstanden und konnte so die Berechnung durchführen.
Ganz habe ich das dort beschriebene Verfahren nicht umgesetzt, aber die 3. und höheren Ableitungen von

Quelltext
1:
cos(2pi (p²-p-1/16)) / cos (2pi p)                    

wollte ich mir dann doch nicht antun. :wink:
Und für die einfache Darstellung braucht man es auch nicht. Die Genauigkeit ist dafür groß genug.

Das kleine Programm zeichnet jetzt die Grafik bis zu einem maximalen t. Durch die eingeschränkte Berechnung habe ich als kleinstes t die 1 gewählt, d.h. unten fehlt ein kleines Stück.
Die Kurve wird außerdem bei mir in Trimetrie gezeichnet, im Original sieht es eher nach Zentralprojektion aus.
Meine Grafik ist auch nicht so schön, wie das Original. Dennoch bin ich sehr zufrieden. :D

Danke noch einmal an alle.

Beste Grüße
(zufriedener) Mathematiker

Anfrage an das Team: Müsste das Thema jetzt eigentlich nach Open Source Projekte verschoben werden? :nixweiss:


Mathematiker - Di 16.04.13 19:03

Hallo,
ich habe noch einmal die Farben geändert und weitere kleine Änderungen durchgeführt (Rev 1).
Zusätzlich kann man auf eine Darstellung in einem ebenen Koordinatensystem umschalten. Dabei werden Real- und Imaginärteil für zeta(0,5 + i t) getrennt dargestellt.
Schneiden beide Kurven die Abszissenachse, so liegt eine der "berühmten" Nullstellen der Zetafunktion vor.

Mal sehen, ob ich auch noch mit hinreichender Genauigkeit diese Nullstellen berechnen kann. :?!?:

Beste Grüße
Mathematiker

Nachtrag: In Rev 2 werden die Nullstellen berechnet. Für die ersten gibt es eine Abweichung in der 3.Dezimalstelle mit einem maximalen relativen Fehler von 0,016 %. Es ist eben nur eine Näherung.
Weiß jemand, wie man schnell die 3.Ableitung von

Quelltext
1:
cos(2pi (p²-p-1/16)) / cos (2pi p)                    

berechnen kann?
Die mit Derive analytisch berechnete Ableitung ist mit der riesigen Zahl von Einzeltermen leider unbrauchbar.

Nachtrag 2: Hat sich erledigt. Die 3.Ableitung ist in der Größenordnung von 10^-11, also für mich hier unwichtig. Die relative Ungenauigkeit entsteht bei der Berechnung der theta-Funktion.


Mathematiker - Do 18.04.13 12:10

Hallo,
das ist die letzte Änderung am Programm (Revision 3).
Mit der Berücksichtigung des 2. und 3.Restglieds sind die berechneten Nullstellen nun auf 3 Dezimalstellen genau.
Etwas tückisch waren die 3. und 6.Ableitung der Hilfsfunktion. Mittels Näherungsformeln funktioniert es aber ganz gut.

Beste Grüße
Mathematiker


Tranx - Do 18.04.13 13:58

Das Ganze hat was von Zyklonen oder Wirbelstürmen. Wer weiß, ob da nicht ein Zusammenhang besteht.


Gammatester - Do 18.04.13 15:51

Ich habe mal den Pugh-C-Code von http://web.viu.ca/pughg/thesis.d/zetaHalfPlusIt.c nach Pascal übersetzt und den grotten langsamen C-Code (alle Aufrufe über power etc) verbessert, ebenso Deine Theta-Funktion.

Der Code unten braucht nur noch ca 1/6 Deiner Zeit (1.28s für 1Mio Aufrufe vs. 8.03s). Außerdem kann man Restterme bis 4.Ordnung berechnen (das bringt wohl aber nicht allzu viel).

Zum Einbau in Deine Unit einfach Dein Zeta durch mein zetacrit ersetzen.

Gruß Gammatester


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
{---------------------------------------------------------------------------}
function PolEvalX(x: extended; const a: array of extended; n: integer): extended;
  {-Evaluate polynomial; return a[0] + a[1]*x + ... + a[n-1]*x^(n-1)}
var
  i: integer;
  s: extended;
begin
  if n<=0 then begin
    PolEvalX := 0.0;
    exit;
  end;
  s := a[n-1];
  for i:=n-2 downto 0 do s := s*x + a[i];
  PolEvalX := s;
end;


{---------------------------------------------------------------------------}
function cterm(n: integer; z: extended): extended;
  {-Coefficients of remainder terms; n can range from 0 to 4}
  { Improved Pascal code from http://web.viu.ca/pughg/thesis.d/zetaHalfPlusIt.c}
const
   n0=22;
   c0: array[0..n0-1of extended = (
          +0.38268343236508977173,
          +0.43724046807752044936,
          +0.13237657548034352332,
          -0.01360502604767418865,
          -0.01356762197010358089,
          -0.00162372532314446528,
          +0.00029705353733379691,
          +0.00007943300879521470,
          +0.00000046556124614505,
          -0.00000143272516309551,
          -0.00000010354847112313,
          +0.00000001235792708386,
          +0.00000000178810838580,
          -0.00000000003391414390,
          -0.00000000001632663390,
          -0.00000000000037851093,
          +0.00000000000009327423,
          +0.00000000000000522184,
          -0.00000000000000033507,
          -0.00000000000000003412,
          +0.00000000000000000058,
          +0.00000000000000000015);

   n1=23;
   c1: array[0..n1-1of extended = (
           -0.02682510262837534703,
           +0.01378477342635185305,
           +0.03849125048223508223,
           +0.00987106629906207647,
           -0.00331075976085840433,
           -0.00146478085779541508,
           -0.00001320794062487696,
           +0.00005922748701847141,
           +0.00000598024258537345,
           -0.00000096413224561698,
           -0.00000018334733722714,
           +0.00000000446708756272,
           +0.00000000270963508218,
           +0.00000000007785288654,
           -0.00000000002343762601,
           -0.00000000000158301728,
           +0.00000000000012119942,
           +0.00000000000001458378,
           -0.00000000000000028786,
           -0.00000000000000008663,
           -0.00000000000000000084,
           +0.00000000000000000036,
           +0.00000000000000000001);

   n2=24;
   c2: array[0..n2-1of extended = (
           +0.00518854283029316849,
           +0.00030946583880634746,
           -0.01133594107822937338,
           +0.00223304574195814477,
           +0.00519663740886233021,
           +0.00034399144076208337,
           -0.00059106484274705828,
           -0.00010229972547935857,
           +0.00002088839221699276,
           +0.00000592766549309654,
           -0.00000016423838362436,
           -0.00000015161199700941,
           -0.00000000590780369821,
           +0.00000000209115148595,
           +0.00000000017815649583,
           -0.00000000001616407246,
           -0.00000000000238069625,
           +0.00000000000005398265,
           +0.00000000000001975014,
           +0.00000000000000023333,
           -0.00000000000000011188,
           -0.00000000000000000416,
           +0.00000000000000000044,
           +0.00000000000000000003);
   n3=24;
   c3: array[0..n3-1of extended = (
           -0.00133971609071945690,
           +0.00374421513637939370,
           -0.00133031789193214681,
           -0.00226546607654717871,
           +0.00095484999985067304,
           +0.00060100384589636039,
           -0.00010128858286776622,
           -0.00006865733449299826,
           +0.00000059853667915386,
           +0.00000333165985123995,
           +0.00000021919289102435,
           -0.00000007890884245681,
           -0.00000000941468508130,
           +0.00000000095701162109,
           +0.00000000018763137453,
           -0.00000000000443783768,
           -0.00000000000224267385,
           -0.00000000000003627687,
           +0.00000000000001763981,
           +0.00000000000000079608,
           -0.00000000000000009420,
           -0.00000000000000000713,
           +0.00000000000000000033,
           +0.00000000000000000004);

   n4=25;
   c4: array[0..n4-1of extended = (
           +0.00046483389361763382,
           -0.00100566073653404708,
           +0.00024044856573725793,
           +0.00102830861497023219,
           -0.00076578610717556442,
           -0.00020365286803084818,
           +0.00023212290491068728,
           +0.00003260214424386520,
           -0.00002557906251794953,
           -0.00000410746443891574,
           +0.00000117811136403713,
           +0.00000024456561422485,
           -0.00000002391582476734,
           -0.00000000750521420704,
           +0.00000000013312279416,
           +0.00000000013440626754,
           +0.00000000000351377004,
           -0.00000000000151915445,
           -0.00000000000008915418,
           +0.00000000000001119589,
           +0.00000000000000105160,
           -0.00000000000000005179,
           -0.00000000000000000807,
           +0.00000000000000000011,
           +0.00000000000000000004);
var
  q: extended;
begin
  q := sqr(z);
  case n of
      0: cterm :=   PolEvalX(q,c0,n0);
      1: cterm := z*PolEvalX(q,c1,n1);
      2: cterm :=   PolEvalX(q,c2,n2);
      3: cterm := z*PolEvalX(q,c3,n3);
    else cterm :=   PolEvalX(q,c4,n4);
  end;
end;


{---------------------------------------------------------------------------}
function theta(t:extended):extended;
  {-Riemann-Siegel-Theta}
var
  x,s: extended;
const
  c0 = 1.0/48.0;
  c1 = 7.0/5760.0;
  c2 = 31.0/80640.0;
  c3 = 127.0/430080.0;
begin
  x := 1.0/sqr(t);
  s := (((c3*x + c2)*x + c1)*x + c0)/t;
  theta := 0.5*t*(ln(t/(2*Pi)) - 1.0) - Pi/8 + s;
end;


{---------------------------------------------------------------------------}
procedure zetacrit(t: extended; var re,im: extended);
  {-Berechne  re + i*im = Zeta(1/2 + i*t) mit Riemann-Siegel}
const
  m=2;  {Max. Ordnung der Korrekturterme, muß <= 4 sein}
var
  i,n: longint;
  axx,axy: extended;
  q,y,p,s,r,tt:extended;
begin
  q  := sqrt(t/(2*Pi));
  n  := trunc(q);

  {s = Summe cos-Terme}
  s  := 0.0;
  tt := theta(t);
  for i:=1 to n do begin
    s := s + 1/sqrt(i)*cos(tt - t*ln(i));
  end;
  s :=2*s;

  {r := Summe Rest-Terme}
  y := 1.0;
  r := 0.0;
  p := 2.0*(q-n) - 1.0;
  for i:=0 to m do begin
    r := r + cterm(i,p)*y;
    y := y/q;
  end;
  r := r/sqrt(q);
  if odd(n+1then r := -r;

  sincos(-tt, axy, axx);

  re := (s + r)*axx;
  im := (s + r)*axy;
end;


Mathematiker - Do 18.04.13 16:33

Hallo Gammatester,
user profile iconGammatester hat folgendes geschrieben Zum zitierten Posting springen:
Der Code unten braucht nur noch ca 1/6 Deiner Zeit (1.28s für 1Mio Aufrufe vs. 8.03s). Außerdem kann man Restterme bis 4.Ordnung berechnen (das bringt wohl aber nicht allzu viel).

Vielen Dank. Das ist richtig schnell und die Nullstellen sind jetzt eine Dezimalstelle exakter.

Ich habe es sofort eingebaut und auf meinem älteren Computer merkt man deutlich die Beschleunigung. Sehr schön.
Jetzt werde ich versuchen, die Berechnung der c-Terme zu verstehen.

Beste Grüße
Mathematiker

Nachtrag: Es hat etwas gedauert :autsch: , bis ich gemerkt habe, dass Gammatester die zeitaufwendige Berechnung exp(-i theta(t)) eliminiert hat. Damit kann die Unit complexm entfernt werden.