Kalle_Worms: Rundungsfehler bei Subtraktion ...

Hallöle,

ja, spinn ich denn? Wenn man von einer ganzen Zahl mehrmals zwei Zehntel abzieht, MUSS man doch irgendwann auf NULL kommen, oder?

Was ist an dieser Funktion (sie bewegt ein Bild auf der X-Achse) falsch? Sie wird angesprungen mit Klick auf "hier"

<a href="javaScript:Move('linux',10,0)">hier</a>

und das testweise angezeigte Ergebnis ist -0.09999999999998121 sowohl in NS 7.1 und im IE 5

var lauf = 0;
var diff = 0.1;
function Move(name,xvon,xbis) {
//window.document.images[name].style.visibility = "visible";
  lauf++;
  if      ( xvon < xbis ) xvon = xvon +diff;
  else if ( xvon > xbis ) xvon = xvon -diff;
  window.document.images[name].style.marginLeft = xvon+'em';
  if (( xvon == xbis ) || ( lauf > 100 )) {
//      ^^^^^^^^^^^^^ xvon wird niemals 0.0
    lauf = 0;
    alert( "xvon=["+xvon+"] xbis=["+xbis+"]" );
  }
  else window.setTimeout("Move('"+name+"',"+xvon+","+xbis+")",5);
}

Lieben Gruß, Kalle

  1. Hallo Kalle,

    ja, spinn ich denn? Wenn man von einer ganzen Zahl mehrmals zwei
    Zehntel abzieht, MUSS man doch irgendwann auf NULL kommen, oder?

    Theoretisch ja. Praktisch ist 1/10, also 0,1 im Binaer-System ohne
    Periode nicht darstellbar. Und da der Computer im Binaer-System
    rechnet und ausserdem nur endlich genau ist, musst du das halt
    beruecksichtigen, indem du z. B. mit 10 multiplizierst und dann
    rechnest oder, bei Vergleichen, mit 0 ± ε rechnest.

    Grüße,
     CK

    --
    Es ist uns nicht möglich, in einem Bereich unseres Lebens richtig zu verhalten, wenn wir in allen anderen falsch handeln. Das Leben ist ein unteilbares Ganzes.
    http://wwwtech.de/
  2. Hallo Kalle,

    und das testweise angezeigte Ergebnis ist -0.09999999999998121 sowohl in NS 7.1 und im IE 5

    das schaut mir nach einem Fall für http://dcljs.de/faq/antwort.php?Antwort=rechnen_rechnen aus.

    Grüße aus Nürnberg
    Tobias

  3. Moin!

    ja, spinn ich denn? Wenn man von einer ganzen Zahl mehrmals zwei Zehntel abzieht, MUSS man doch irgendwann auf NULL kommen, oder?

    Ein Grundsatz beim Rechnen mit Fließkommazahlen im Rechner lautet: Es gibt immer Rundungsfehler. Deshalb kann man niemals darauf vertrauen, dass nach Ablauf von einem (oder gar mehreren) Rechenschritten ein gewünschter Zielwird wirklich zu 100% exakt getroffen wird, so dass man ihn mit "==" abfragen kann, sondern man sollte immer damit rechnen, dass man nur Werte erreicht, die "knapp daneben" liegen.

    Für deinen Fall bedeutet das zwei mögliche Lösungsansätze:

    1. Wenn du deine Funktion ein wenig umschreibst, so dass in einer Variablen die Bewegungsrichtung eindeutig festgelegt ist, dann könntest du einfach abfragen, ob xvon größer als xbis ist (bei Vorwärtsbewegung, d.h. Addieren positiver Werte) bzw. ob xvon kleiner als xbis ist (bei Rückwärtsbewegung), und dann xvon einfach gleich xbis setzen.

    2. Alternativ kannst du prüfen, ob die Differenz von xvon und xbis ziemlich klein ist. Wie klein "klein" sein soll, hängt natürlich vom Einzelfall ab, wenn du eine Schrittweite von 0,1 hast, sollte die Differenz abs(xvon-xbis) < 0,1  sein, denn dann liegst du in einem Bereich von weniger als einer Schrittweite von deinem Zielwert und könntest dann einfach xvon = xbis setzen. Für eine Animation sollte das ausreichen.

    - Sven Rautenberg

  4. für eure Hilfe. Habe mit Rundungsfehlern natürlich nur bei Multiplikation und Division gerechnet.

    Ist das ungenaue Addieren und Subtrhieren eine Spezialität von JavaScript?

    Jedenfalls runde ich nun, und es klappt:

    // OHNE RUNDUNG UNGENAU WG. HEXAZAHL:
      if      ( xvon < xbis ) xvon = Math.round(( xvon +diff )* 100 ) / 100;
      else if ( xvon > xbis ) xvon = Math.round(( xvon -diff )* 100 ) / 100;
      window.document.images[name].style.marginLeft = xvon+'%';
      if ( xvon == xbis ) {
      ...
      }

    1. Hallo Kalle,

      Ist das ungenaue Addieren und Subtrhieren eine Spezialität von
      JavaScript?

      Nein. Wie gesagt, das kann bei jeder Operation passieren,
      versuche z. B. 0,1 im Binaer-System darzustellen -- da _muss_
      gerundet werden.

      Grüße,
       CK

      --
      Wenn gewöhnliche Menschen Wissen erlangen, sind sie weise. Wenn Weise Einsicht erlangen, sind sie gewöhlnliche Menschen.
      http://wwwtech.de/