Pi
-
also ich nahm mal an, daß sich da irgendwelche fehler aufsummiert haben und hab das prog leicht umgebaut, damit ich das besser verfolgen kann.
#include<stdio.h> #include<math.h> void main() { double i,pi,nen,zal; pi=0.0; nen=1.0; zal=1.0; for(i=0;i<10000000;i+=2) { pi+=1.0/(2*i+1); pi-=1.0/(2*i+3); } printf("%.20lg\n",pi*4); printf("%.20lg\n\n",atan(1)*4); }
ausgabe:
3.141592 5 5358979 15
3.141592 6 5358979 31ich lach mich kringelig, da stimmt irgendwas ganz und gar nicht.
wenn ich 10mal mehr zahlen nehme passiert das hier:
3.1415926 4 3589 326
3.1415926 5 3589 7931edit: mir scheint, wenn man nur 10000000 (1 mit 7 nullen) reihenglieder nimmt, darf man nicht mehr als 7 stellen genauigkeit erwarten.
daß allerdings so viele stellen nachher stimmen, ist ein wunder.double i,pi,nen,zal,sign; pi=0.0; nen=1.0; zal=1.0,sign=1; for(i=1;i<1000;i+=2) { pi+=sign/i; sign=-sign; }
also nur 500 glieder!
3.1395926555897851
3.1415926535897931
12 übereinstimmungen! was ist denn da los?[ Dieser Beitrag wurde am 30.11.2002 um 19:53 Uhr von volkard editiert. ]
-
irgendwie seltsam, gell? :p
-
huhuhuu *kringel*
Jungs also da kann irgendwas net stimmen.
Aber ist doch schon Lustig was für Käfer ( bugs) so alles auftauchen könnenmfg
-
das könnte durch die rechenungenauigkeit der fpu kommen, es ist ganz legitim, dass ab ein paar stellen die genauigkeit nicht mehr vorhanden ist, dass es mal stimmt und später nicht mehr liegt vielleicht daran dass auch andere inputwerte kommen und somit ne art rauschen vorhanden ist.
es kann ganz schlimm werden wenn man 2 rechner per netzwerk synchronisieren muss, von denen einer AMD und einer INTEL ist, dafür mußte ich dann ne eigene mathlib machen, die auf der ALU rechnet, nicht fpu.
vielleicht liegt es auch an was ganz anderem bei euch, is nur ein tip.
-
erst lesen, dann mitreden.
ausgabe:
3.141592 5 5358979 15
3.141592 6 5358979 31
frage ist doch nicht, warum der erste fehler bei der 7. nachkommastelle ist, sondern weshalb danach 7 korrekte stellen sind.
-
"erst lesen, dann mitreden" dito
es darf ein rauschen geben, das kann cpu abhängig sein. (ein bit falsch nach zig stellen ist ein kleines rauschen, genau das meinte ich!)
außerdem hab ich geschrieben, dass es vielleicht nichts mit eurem problem zu tun hat, so ne dumme anmache kann man sich sparen, wollte ja nur helfen.
rapso->greets();
-
... das Verfahren zyklisch arbeitet treten auch die Fehler
zyklisch auf - würde ich jetzt mal so sagen. Zudem ist Pi ne
normale Zahl (siehe Wikipedia), evtl. haben solche Zahlen ein
solches Verhalten?
-
Hallo
Geht doch viel einfacher: Lern' einfach 50..100 Stellen von Pi auswendig, dann
brauchst Du keinen PC oder Taschenrechner mehr, um Pi mit vernünftiger Genauigkeit zu benutzen.14159 26535 89793 23846
26433 83279 50288 41971
...Langeweile? Nie gehört
Grüße
-
Was wäre, wenn ihr die Summationsschleife rückwärts läufen laßt? Möglicherweise würden sich dann die Rechenfehler, die aus der Addition von einer großen zu einer kleinen Zahl ergeben weniger stark ausfallen.
-
Hm, scheint nur bedingt was zu bringen. Wenn man allerdings die Ergebnisse mal ohne die Multiplikation mit 4 anschaut sind die Abweichungen größer. Allerdings läßt sich durch Erhöhung der Schleifendurchläufe auch die Genauigkeit erhöhen.
Könnte mir vorstellen, daß das beim Rückwärtsdurchlauf etwas besser geht als vorwärts.
-
@rapso: Na mach dir nix draus, so ist der volki halt.
rapso schrieb:
es darf ein rauschen geben, das kann cpu abhängig sein. (ein bit falsch nach zig stellen ist ein kleines rauschen, genau das meinte ich!)
Trotzdem komisch, denn es ist nicht ein Bit. Es ist eine Zahl in der Dezimaldarstellung, und das bedeutet normalerweise viele Bits in der Binärdarstellung.
Gruß, TGGC (\-/ returns)
-
warum lasst ihr die toten nicht in frieden ruhen?
-
Cpt. Tanga schrieb:
warum lasst ihr die toten nicht in frieden ruhen?
Warum schreibst du Sachen, die nicht zum Thema passen? f'`8k
Gruß, TGGC (\-/ returns)
-
Warum Gleitkommazahlen an Genauigkeit verlieren können
Siehe auch
Codeoptimierung
Dezimale Gleitkommawerte können im Allgemeinen binär nicht exakt dargestellt werden. Das ist ein Nebeneffekt der Darstellungsweise von Gleitkommazahlen durch die CPU. Aus diesem Grund könnte ein gewisser Genauigkeitsverlust auftreten, und manche Gleitkommaoperationen können unerwartete Ergebnisse hervorbringen.Dieses Verhalten kann auf die folgenden Umstände zurückgeführt werden:
Die Binärdarstellung der Dezimalzahl ist möglicherweise nicht genau.
Es gibt einen Typenkonflikt zwischen den verwendeten Zahlen (z. B., wenn float und double gemischt werden).
Um das Verhalten zu korrigieren, stellen die meisten Programmierer entweder sicher, dass der Wert größer oder kleiner als benötigt ist, oder sie verwenden eine BCD (Binary Coded Decimal)-Bibliothek, durch die Genauigkeit gewährleistet wird.Auszug aus dem MSDN
-
Dann will ich mich auch mal das Thema aufwärmen:
Mit Gleitkommarechung hat das Ganze - soweit ich das Problem durchschaue - nix zu tun. In exakter Rechung (d.h. gerundet wird erst nach der Summation!) ergibt sich mit Maple:
> e(10) := evalf(4*sum((-1)^k / (2*k + 1),k=0..10)) - evalf(Pi); > e(100) := evalf(4*sum((-1)^k / (2*k + 1),k=0..100)) - evalf(Pi); > e(1000) := evalf(4*sum((-1)^k / (2*k + 1),k=0..1000)) - evalf(Pi); > e(10000) := evalf(4*sum((-1)^k / (2*k + 1),k=0..10000)) - evalf(Pi); > e(100000) := evalf(4*sum((-1)^k / (2*k + 1),k=0..100000)) - evalf(Pi); e(10) := 0.0907231558157994488 e(100) := 0.0099007474811973368 e(1000) := 0.0009990007497498124 e(10000) := 0.0000999900007499750 e(100000) := 0.0000099999000007500
Ich vermute jetzt einfach mal, dass wird sich so weiter fortsetzen. Warum der absolute Fehler solch eine Gestalt hat, ist mir auch ein Rätsel...
-
Leute, das ist doch nicht so schwer... Stichwort Numerik...
in der summation kommt z.B. "zal/nen" vor und "nen" wird u.A. mal 3.0, also haben wir dort mal "zal/3.0" und zal ist konstant 1.0, also haben wir in der summe eine "1/3" und das ist 0,3333333... mit UNENDLICH vielen 3en dahinter - der speicher für ein objekt beliebigen typs ist aber ENDLICH, weil der RAM immer endlich ist (für unendlich viel ram bräuchte man unendlich viele atome, in unserem universum gibt's aber nur endlich viele atome...), also kann man den wert NIEMALS vollständig explizit darstellen - man könnte ne klasse für brüche benutzen, damit der wert nicht mehr explizit dargestellt wird...
soll heissen: wir kriegen dort summenglieder, die nicht so exakt dargestellt werden können, wie sie müssten - eine abweichung ist bei expliziter darstellung der werte unausweichlichund dass mehr durchläufe nix bringen liegt daran, dass ab einem gewissen wert für "nen" einfach "zal/nen = 0" (weil die werte so klein werden, dass sie gar nicht mehr explizit darstellbar sind) - und 0 kann man schließlich beliebig oft dazu addieren, ohne was zu verändern...
dass nach den 3 abweichenden stellen wieder 3 übereinstimmende stellen vorkommen, halte ich für zufall.
also: entweder ne klasse für brüche benutzen oder nen Datentyp mit mehr Speicher benutzen (long double), es gibt auch datentypen, bei denen man die genauigkeit festlegen kann (die benutzen idR keine bits, sondern arrays/listen von shorts, wo jeder short einer ziffer in dezimaldarstellung entspricht) - solche datentypen benutzen übrigens mathematikprogramme wie maple (und die setzen die genauigkeit halt sehr hoch, richtung 30-50 stellen hinter'm komma, womit sich die besseren ergebnisse erklären)...
ich hab aber grad mal durchgetestet, dass klassen für brüche auch nicht der hit sind: ich hab mal schnell nen code geschrieben, der das ganze explizit so berechnet, wie es ne bibliothek für brüche intern machen würde:
long double z=1.0, n=1.0; for(long double i=3;i<=3210;i+=4) { z = (z*i-n)*(i+2)+n*i; n *= i*(i+2); } cout.precision(10); cout << 4.0*(z/n) << '\n';
mit ner grenze über 3210 wird z oder n schon so groß, dass das nicht mehr funktioniert und bei der grenze 3210 kommt man lediglich auf pi=3.142215706... man könnte vielleicht hin und wieder zwischenergebnisse fest halten und z und n zurücksetzen, damit die werte nicht so exorbitant wachsen... ich versuch das gleich mal...
-
AlgorithMan schrieb:
das ist 0,3333333... mit UNENDLICH vielen 3en dahinter - der speicher für ein objekt beliebigen typs ist aber ENDLICH, weil der RAM immer endlich ist
Du hast in deinem Posting die Zahl "0,3333333... mit UNENDLICH vielen 3en dahinter" offenbar mit endlich viel Speicher beschrieben. Um genau zu sein hast du genau strlen("0,3333333... mit UNENDLICH vielen 3en dahinter") = 46 Bytes benötigt, um diese Zahl eindeutig zu beschreiben. Das ist weit von unendlich entfernt.
Worauf ich hinaus will: Die fehlende Genauigkeit hat nichts mit dem endlichen RAM zu tun, sondern damit, wie ein double versucht die reellen Zahlen zu modellieren.
Auch unendlich lange Zahlen wie "0,3333333... mit UNENDLICH vielen 3en dahinter" und pi lassen sich mit endlich viel Speicher exakt darstellen; man nennt diese Zahlen deswegen auch "berechenbar".
-
Christoph schrieb:
...und pi lassen sich mit endlich viel Speicher exakt darstellen
aber nicht als zahl.
-
also, wie versprochen hab ich das mal mit speicherung von zwischenergebnissen versucht - das hat soweit ganz gut geklappt, die grenze von i<=3510 hab ich bei weitem gesprengt - jetzt kommt i bis 5.000.000.000 und da ist auch noch nicht schluss
long double z=0.0, n=1.0, pi=0.0, i=1.0; for(int k = 0; k < 50000000; k++) { for(int j = 0; j < 25; j++, i+=4.0) { // zwischenergebnis berechnen z = (z*i+n)*(i+2)-n*i; n*=i*(i+2); } pi += (z/n)*4.0; // zwischenergebnis addieren n=1.0; // n und z zurücksetzen z=0.0; } cout.precision(12); cout << pi << '\n';
damit komme ich auf pi=3.141 592 653 19, weicht also erst ab der 10. stelle hinter'm komma vom richtigen wert (3,141 592 653 58...) ab. vermutlich würde das ergebnis noch besser, wenn man k noch weiter laufen lassen würde, aber ich hab jetzt keine lust mehr, das weiter durchzutesten, weil man mit i bis 5.000.000.000 schon ziemlich lange warten darf
der thread ist zwar alt, ich find das thema aber so wichtig, dass man da ne ausführliche antwort auf die frage braucht, deshalb hab ich das mal aufgewärmt...
-
@Christoph: "0,3333333... mit UNENDLICH vielen 3en dahinter" ist keine explizite darstellung.
@fricky: doch, auch als zahl: 1/3, aber das ist auch keine explizite darstellung