Ein lästiger Rundungsfehler und eine Erklärung.
Lasst uns eine einfaches Beispiel in JavaScript berechnen.
var sum = 0.1 + 0.2; console.log(sum)
Wir würden uns das Ergebnis 0.3 erwarten, nicht wahr? JavaScript liefert uns allerdings folgendes:
// sum == 0.30000000000000004
Um zu verstehen, warum das so ist, muss man wissen, wie Zahlen in JavaScript verwaltet werden. In JavaScript existiert für Zahlen nur ein Datentyp: Number.
Jede Zahl wird also in einer binären Exponential-Repräsentation abgebildet. Für Ganzzahlwerte bedeutet dies, dass eine gesicherte Darstellung bis 15 Ziffern möglich ist, bevor Rundungsfehler bedingt durch die exponentielle Abbildung auftreten. Integer sind bis 15 Stellen sicher.
var x = 999999999999999; // 999999999999999 var y = 9999999999999999; // 10000000000000000
Bei Fließkommazahlen wirkt sich dies entsprechend auf die Genauigkeit der Nachkommastellen aus (siehe erstes JavaScript Beispiel).
JavaScript steht nicht allein da.
Wer sich nun bestätigt fühlt, dass JavaScript eine total verkorkste Sprache sei und nicht einmal ordentlich rechnen kann, wird erstaunt sein, dass dieses Problem nicht allein auf JavaScript beschränkt ist.
Alle Sprachen, welche Fließkommazahlen nach IEEE 754 implementieren, weisen entsprechende Rundungsfehler auf. Der Unterschied besteht lediglich in den diversen Sprachen sich unterscheidenden zusätzlichen Datentypen.
hier das selbe Beispiel mit JAVA:
public static void main(String[] args) {
double sum = 0.2 + 0.1;
System.out.println(sum);// sum == 0.30000000000000004
}
Wie kann man solche Rundungsfehler vermeiden?
Ja nach Programmiersprache, sollte man prüfen, ob der Umstieg auf einen anderen Datentyp Sinn macht. So kann man bei Java den Datentypen BigDecimal nutzen:
Beispiel Java mit BigDecimal:
public static void main(String[] args) { BigDecimal b1 = new BigDecimal("0.2"); BigDecimal b2 = new BigDecimal("0.1"); BigDecimal b3 = b1.add(b2); System.out.println(b3); //b3 == 0.3 }
Möchte man in JavaScript korrekt rechnen, sollte man sich bignumber.js oder BigDecimal.js genauer anschauen.
Alternativ kann man sich in JavaScript auch mit einem gewöhnlichen parseFloat und toPrecision helfen:
var sum = parseFloat((0.1+ 0.2).toPrecision(1));
console.log(sum);
// sum == 0.3