Jan 23

Ungenaue Ergebnisse beim Rechnen mit gebrochenen Zahlen

Tag: Allgemeines,JavascriptPatrick @ 1:41 am

Während der Weiterentwicklung an meiner Demoseite zur Darstellung von mathematischen Funktionen durch Javascript, stieß ich auf einige Ungereimtheiten der in der Schleife verwendeten Laufvariablen i. Eine genauere Überprüfung brachte für mich völlig unerklärliche Werte zum Vorschein. Die einfache Gleichung 0.2 + 0.1 ergab nicht wie erwartet 0.3 sondern 0.30000000000000004.

Ich konnte es mir absolut nicht erklären, woher dieser – in meinen Augen – Fehler zu Stande kam. Ich schloß sämtliche Fehlerquellen aus. Als dies auch nichts half, beschloss ich der Sache auf den Grund zu gehen – ohne vorher zu ahnen, dass ich mit meiner so simplen Rechnung auf eine in Kauf genommene Schwachstelle unserer heutigen schnellen Computertechnik gestoßen war. Doch der Reihe nach.

Als erstes sei klargestellt, dass die nachfolgend beschriebene Ungenauigkeit nur bei Kommarechnung auftriit – da jedoch in jeder Programmiersprache, egal ob Javascript, PHP oder C. Integerzahlen bleiben davon gänzlich unberührt.

Um das angesprochene Problem deutlich zu machen, habe ich eine Testseite erstellt, auf der man eine Tabelle sieht, in deren linken Spalte sich die Zahlenwerte von 0 bis „ungefähr 1.9“ befinden. Die Werte werden in einer for-Schleife mit dem Startwert 0, der Abbruchbedingung kleiner-gleich 2 und einer Erhöhung der Laufvariable um jeweils 0.1 pro Durchlauf erzeugt und via jQuery an die Tabelle angehangen.

Wie man unschwer erkennen kann, weichen eine Vielzahl der in der linken Tabellenhälfte stehenden Werte geringfügig vom erwarteten Wert ab. Es tritt eine Ungenauigkeit auf.

Die Ursache des „Problems“ liegt in der binären Darstellung von Zahlen innerhalb von Programmen. So wird die Zahl 15 intern als 00001111 im Speicher abgelegt. Das selbe geschieht auch mit Kommazahlen, jedoch kann es dabei zu Ungenauigkeiten in der Darstellung kommen, da eine Vielzahl gebrochenener Zahlen binär periodisch abgebildet wird. So entspricht 0.1 im Dualsystem der Ziffer 1.1001 E-101, wobei E den Exponenten symbolisiert.

Eine ausführliche Abhandlung findet man auf DCLJS.

Um in Javascript dem Problem ein wenig aus dem Weg zu gehen, nutze ich die numlib-Bibliothek, die unter anderem eine Funktion namens dezRound zum Runden einer beliebigen Anzahl von Nachkommastellen zur Verfügung stellt. Mit dieser Funktion stelle ich sicher, dass Zahlen mit relativ wenigen Nachkommastellen genau angegeben werden – ich entschied mich auf 9 Stellen zu runden. Leider baue ich dadurch bei längeren gebrochenen Zahlen selbst eine Ungenauigkeit durch das Runden ein, die ich aber in meinem Fall in Kauf nehme.

Eine Antwort zu “Ungenaue Ergebnisse beim Rechnen mit gebrochenen Zahlen”

  1. Mathematische Funktionen mit flot darstellen - Teil 2 | Ajaxschmiede.de sagt:

    […] zur Darstellung mathematischer Funktionen mittels flot weiterzuentwickeln. Dabei entdeckte ich die fehlerhafte Darstellung gebrochener Zahlen in heutigen PC-Systemen und etliche andere Kleinigkeiten, auf die ich gleich eingehen werde. […]

Hinterlasse einen Kommentar

You must be logged in to post a comment.