Rechenungenauigkeit mit Javascript – Warum?

Schonmal in Javascript über ungenaue Berechnungen aufgeregt?

<script>
alert(0.2 + 0.4);
</script>

Ergebnis?

Das Problem ist mit parseFloat ja schnell behoben, aber darum gehts mir hier garnicht. Warum kriegt Javascript kein sauberes Ergebnis zustande, wohingegen bei 0.2 + 0.3 glatt 0.5 rauskommt? Javascript rechnet intern binär. Und Zahlen, die im Zehnersystem wunderbar aufgehen, können im Dualsystem unter Umständen periodisch sein. So auch die 0.6. Schauen wir uns mal die Berechnung an:

  1. Vor dem Komma hat unser Ergebnis logischerweise eine 0
  2. Die Zahl wird mit 2 multipliziert (0.6 * 2 = 1.2)
  3. Der „Vorkommaanteil“ von oben ist die erste Stelle der gesuchten Binärzahl, also 1. Damit haben wir bisher 0.1
  4. Jetzt wird die Vorkommastelle weggeworfen und der Rest wieder mit 2 multipliziert. Heißt: Aus 1.2 wird 0.2. Nun ergibt 0.2 * 2 = 0.4 -> Damit ist die nächste Nachkommastelle des Ergebnisses wieder eine 0, also bisher 0.10
  5. Das geht jetzt immer so weiter: 0.4 * 2 = 0.8 -> Wieder eine 0 mehr
  6. 0.8 * 2 = 1.6 -> Eine 1 dazu
  7. 0.6 * 2 = 1.2 -> Eine 1 dazu
  8. Ab hier wiederholt sich das Ganze (siehe zweiter Schritt). Damit ist das Ergebnis 0.10011 10011 10011 10011 …..

Die ebenfalls angesprochene 0.5 hat das Problem nicht. Die ergibt binär nämlich glatt 0.1.

Fazit

Javascript kann nur „glatte“ Zahlen liefern, wenn das Ergebnis im Binärsystem nicht periodisch ist.

Weitere Posts:

Dieser Beitrag wurde unter Javascript, webdev veröffentlicht. Setze ein Lesezeichen auf den Permalink.

3 Antworten auf Rechenungenauigkeit mit Javascript – Warum?

  1. Pingback: Best-of-the-Web 5 | davblog: webdev and stuff

  2. Christoph sagt:

    IBM wollte eine entsprechende Änderung des ECMAScript Standards durchsetzen, ist aber damit nicht durchgekommen.. Schade eigentlich..

  3. Jannik sagt:

    @Christoph: da kann man keine Änderung durchbringen, da Fließkomma eben immer Ungenauigkeiten haben (das liegt in der Natur der Sache). Und mit beliebiger Genauigkeit wird die Rechnung um mehrere Größenordnungen langsamer.

    Sehr lustig ist auch das folgende (unintuitive aber logische) Codebeispiel in PHP:

    var_dump( intval((0.1 + 0.7) * 10) === 7 ); // true

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.