kaepten: Rechnungsfehler, aber warum?

Hallo Forum

Ich rätsle grad an einem Rechnugsfehler rum und weiss nicht wieso das ist und vorallem finde ich auch keine Lösung. Vielleicht weiss jemand von euch Rat. es geht hierum:

  
var angle= 7.26;  
var deg = parseInt(angle);  
var min = parseInt( (angle-deg)*100 );  

Ich kriege für min immer 25, erwarten würde ich 26! Und zwar weil (angle-deg) 0.2599999999999998 ergibt. Kann mir das jemand erklären? Oder besser: gibt es eine Lösung? Klar kann ich runden, aber wieso muss ich etwas runden, was eigentlich präzis war?

Vielen Dank für Tipps!

  1. Hi,

    Ich rätsle grad an einem Rechnugsfehler rum

    var angle= 7.26;
    var deg = parseInt(angle);

    deg ist also jetzt 7.

    var min = parseInt( (angle-deg)*100 );

    Ergibt theoretisch (7.26-7)*100 = 26.
    Aber da gebrochene Zahlen, die im Zehnersystem ganz harmlos aussehen, als Bruch in der Binärschreibweise (so funktioniert die Fließkommadarstellung üblicherweise) oft nicht exakt dargestellt werden können, ergeben sich solche Rundungsfehler.

    Ich kriege für min immer 25, erwarten würde ich 26! Und zwar weil (angle-deg) 0.2599999999999998 ergibt.

    Zum Beispiel, ja.

    gibt es eine Lösung? Klar kann ich runden

    Genau das ist die Lösung.

    aber wieso muss ich etwas runden, was eigentlich präzis war?

    Weil das, was für unsere Augen präzise ist, im Binärsystem eben *nicht* präzise ist.

    Ciao,
     Martin

    --
    Die letzten Worte des Hardware-Bastlers:
    Das Netzkabel lass ich wegen der Erdung lieber dran.
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
  2. @@kaepten:

    nuqneH

    aber wieso muss ich etwas runden, was eigentlich präzis war?

    Forumsstartseite: „Lies unsere FAQ, dort sind häufig gestellte Fragen direkt beantwortet.“

    Vielen Dank für Tipps!

    Unten anfangen zu lesen.

    Qapla'

    --
    Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
    (Mark Twain)
    1. Danke für den Hinweis. Ahnte nicht, dass es sich um so ein populäres "Proplem" handelt.

      kaepten

      1. @@kaepten:

        nuqneH

        Danke für den Hinweis. Ahnte nicht, dass es sich um so ein populäres "Proplem" handelt.

        Na dann: Oben anfangen zu lesen! ;-)

        Qapla'

        --
        Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
        (Mark Twain)
      2. Hallo,

        Ahnte nicht, dass es sich um so ein populäres "Proplem" handelt.

        ... und bei Problemen mit der Rechtschreibung wenden Sie sich an die Rechtschreibprüfung Ihres Vertrauens.

        Ciao,
         Martin

        --
        Husten kann böse Folgen haben.
        Besonders im Kleiderschrank.
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
  3. Hallo,

    gibt es eine Lösung?

    <script>  
    var angle= 7.26;  
    var deg = parseInt(angle);  
    var min = parseInt( (angle-deg)*100 );  
    alert(min);  
    </script>  
    <script>  
    var angle= 7.26;  
    var deg = parseInt(angle);  
    var min = parseInt(angle*100 - deg*100);  
    alert(min);  
    </script>
    

    Viele Grüße Novi

    --
    "(...) deshalb mag ich Binärtechnik. Da gibt es nur drei Zustände: High, Low und Kaputt." (Wau Holland)
    1. var angle= 7.26;
      var deg = parseInt(angle);
      var min = parseInt(angle*100 - deg*100);

      Dumme Frage, wieso ist das so?
      Der Theorie nach wird bereits 7.26 »ungenau« binär repräsentiert, oder? Also müsste die Abweichung ja schon bei der Rechnung 7.26 * 100 auftreten, oder meinetwegen bei 7.26 - 6. Wieso tritt es nur bei 7.26 - 7 auf? Weil da eine 0 vor dem Komma steht?
      Kann mir das jemand einfach erklären?
      http://en.wikipedia.org/wiki/Double_precision_floating-point_format

      Mathias

      1. Das eine ist vielleicht eine Abweichung nach oben, das andere eine nach unten, ich habs mir nicht durchgerechnet. Dann passts im zweiten Beispiel wieder, aber auch nur durch Zufall.
        Ich rechne bei solchen Spielereien wenn möglich auch immer zuerst mal und dann geteilt.
        Und man sollte sich bewusst machen dass parseInt oder ein Cast immer nur abschneidet und nicht rundet.

      2. var angle= 7.26;
        var deg = parseInt(angle);
        var min = parseInt(angle*100 - deg*100);

        Dumme Frage, wieso ist das so?
        Der Theorie nach wird bereits 7.26 »ungenau« binär repräsentiert, oder? Also müsste die Abweichung ja schon bei der Rechnung 7.26 * 100 auftreten, oder meinetwegen bei 7.26 - 6. Wieso tritt es nur bei 7.26 - 7 auf? Weil da eine 0 vor dem Komma steht?

        Vermutlich weil 7.26 * 100 automatisch in ein integer umgewandelt wird. Was aus diversen Gründen sinnvoll ist.

        alert(7.26 * 100 == parseInt(7.26 * 100));

        Struppi.

      3. @@molily:

        nuqneH

        var angle= 7.26;
        var deg = parseInt(angle);
        var min = parseInt(angle*100 - deg*100);

        Dumme Frage, wieso ist das so?

        Ist das so?

        Bei mir ergibt sich dieses Bild:

        Siehe selbst: http://bittersmann.de/samples/floating-point-calculation/floating-point-calculation.php

        Qapla'

        --
        Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
        (Mark Twain)
        1. Dumme Frage, wieso ist das so?

          Ist das so?

          Bei mir ergibt sich dieses Bild:

          Ich würde mal sagen, das liegt an den unterschiedlichen "rounding modes" der Sprachen bzw. der verwendeten Math Bibliotheken.

          Struppi.

        2. Hallo Gunnar,

          Bei mir ergibt sich dieses Bild:

          Das liegt aber daran, dass ich in PHP 5.3 dafür gesorgt habe, dass es sich so verhält, wie man naiverweise erwarten würde und nicht einfach runde(Zahl*10^n)/10^n ausführt, was JS macht. Ich hatte damals den C-Algorithmus auch nach JS und PHP selbst (für 5.2) portiert gehabt und im Forum gepostet:

          http://forum.de.selfhtml.org/archiv/2008/10/t178373/#m1176613
          (Siehe auch den ganzen Thread für weitergehende Erklärungen.)

          Viele Grüße,
          Christian

          1. Tach.

            Das liegt aber daran, dass ich in PHP 5.3 dafür gesorgt habe, dass es sich so verhält, wie man naiverweise erwarten würde und nicht einfach runde(Zahl*10^n)/10^n ausführt, was JS macht.

            Ich weiß ja nicht, ob Gunnars Server lügt, wenn er sagt, daß PHP 4.4.9 läuft ... ;-) Jedenfalls kriege ich auch mit Version 5.2.10 Gunnars Ergebnis. Ist Dein Patch auch in diesen Zweig eingeflossen?

            --
            Always remember that you are unique. Just like everybody else.
            1. Hallo,

              Das liegt aber daran, dass ich in PHP 5.3 dafür gesorgt habe, dass es sich so verhält, wie man naiverweise erwarten würde und nicht einfach runde(Zahl*10^n)/10^n ausführt, was JS macht.

              Ich weiß ja nicht, ob Gunnars Server lügt, wenn er sagt, daß PHP 4.4.9 läuft ... ;-) Jedenfalls kriege ich auch mit Version 5.2.10 Gunnars Ergebnis. Ist Dein Patch auch in diesen Zweig eingeflossen?

              Jain. Wie ich im verlinkten Archivthread schrieb machte PHP schon eine ganze Weile etwas in die Richtung (nur mit relativ viel unerwünschten Nebeneffekten), was hier halt zufälligerweise wie gewünscht funktioniert. Wirklich "richtig" (so man denn bei dieser Problemstellung von "richtig" sprechen kann) verhält sich PHP erst seit 5.3.

              Viele Grüße,
              Christian

              PS @Gunnar: Wenn Dein Server wirklich noch PHP 4.4.9 ausliefert, solltest Du *dringend* upgraden. ;-)

  4. @@kaepten:

    nuqneH

    var angle= 7.26;
    var deg = parseInt(angle);

    Wieso parseInt(angle)? angle ist doch ein numerischer Wert. Math.[ref:self812;javascript/objekte/math.htm#floor@title=floor](angle) sollte schneller sein.

    Qapla'

    --
    Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
    (Mark Twain)
    1. @@kaepten:

      nuqneH

      var angle= 7.26;
      var deg = parseInt(angle);

      Wieso parseInt(angle)? angle ist doch ein numerischer Wert. Math.[ref:self812;javascript/objekte/math.htm#floor@title=floor](angle) sollte schneller sein.

      Qapla'

      Weil der Code gar nicht von mir, sondern aus einer Library einer grösseren schweiz. Institution ist. Auch aus diesem Grunde, bin ich blauäugig von einem "massiven" Problem ausgegangen. Weil ich dachte, dass die nur gut geprüfte Libraries in die Welt schicken.

      Wenn ich das aber dank der Hilfe hier lösen kann, werde ich denen sicher ein Feedback geben.