Pi



  • 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 unausweichlich

    und 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 😉



  • AlgorithMan schrieb:

    @fricky: doch, auch als zahl: 1/3, aber das ist auch keine explizite darstellung

    das meinte ich ja. als zahl passt es nicht, auch wenn du alle computer dieser welt zusammenschaltest.
    🙂



  • Selbstverständlich geht das: http://www.computer-museum.ru/english/setun.htm



  • Es gibt aber für Pi keine explizite Darstellung. Pi ist bekannterweise irrational und lässt sich daher bestenfalls als unendliche Reihe darstellen. Auch dabei wird man aber offensichltich irgendwann an Speichergrenzen stoßen.

    PS: Man sollte vielleicht wissen, das Pi aufgrund der oben beschriebenen Gründe NICHT periodisch ist.



  • Bla, nur wenn man ein Stellenwertsystem mit natürlichen Zahlen nimmt. Was hält mich denn davon ab, in Vielfachen von π, π^2 etc. zu rechnen?



  • .filmor schrieb:

    Bla, nur wenn man ein Stellenwertsystem mit natürlichen Zahlen nimmt. Was hält mich denn davon ab, in Vielfachen von π, π^2 etc. zu rechnen?

    Und das bringt Dir dann was?
    Pi ist unendlich lang und NICHT periodisch. Da kannst Du noch so tolle Bildräume konstruieren.



  • Das bringt mir, dass ich Pi in endlichem Speicher darstellen kann. Es gibt (bis auf praktische Überlegungen) keine Gründe, dass Binär- oder Dezimalsystem zu bevorzugen (beim Dezimalsystem ist es sogar noch viel mehr Konvention, eigentlich ist 10 keine besonders tolle Basis).



  • Unendllich ist undendlich. Egal, in was für einem System man versucht es darzustellen. Pi lässt sich nicht numerisch exakt darstellen. Aber Du kannst ja gerne mal ein Gegenbeispiel bringen und π\pi als erster Mensch exakt darstellen. Oder 2\sqrt{2}, 3\sqrt{3} etc. oder die Eulersche Zahl. Viel Spaß.



  • .filmor schrieb:

    Selbstverständlich geht das: http://www.computer-museum.ru/english/setun.htm

    mit analogrechnern geht's natürlich auch noch. da sieht man mal wieder, mit was für einer schlechten technik wir uns umgeben.
    🙂



  • ~fricky schrieb:

    .filmor schrieb:

    Selbstverständlich geht das: http://www.computer-museum.ru/english/setun.htm

    mit analogrechnern geht's natürlich auch noch. da sieht man mal wieder, mit was für einer schlechten technik wir uns umgeben.
    🙂

    Aber nur theoretisch.


Anmelden zum Antworten