5.9 Numerische Gleitpunktprobleme
Vorsicht ist geboten vor Ungenauigkeiten durch die binäre Darstellung von Gleitpunktzahlen. Reelle Zahlen können im Gleitpunktformat nicht immer exakt dargestellt werden. Das liegt daran, dass die Gleitpunktsemantik so implementiert ist, wie es der Prozessor berechnet. Würde man dafür eine extra Funktion für den Compiler schreiben, wäre die Berechnungsdauer systemabhängig. Würde die Berechnung beispielsweise bei einem Pentium-Prozessor optimal ablaufen, könnte sie bei einem Athlon wiederum katastrophale Laufzeiten haben. Dadurch kann es bei der Berechnung von arithmetischen Ausdrücken zu Ungenauigkeiten kommen (wie weiter oben schon gezeigt wurde).
Achtung |
Zahlen im Gleitpunktformat sollten nie auf Gleichheit überprüft werden! |
Folgendes Programm wird in eine Endlosschleife laufen, da die Zahl 0.1 nie exakt dargestellt werden kann:
/* never_ending.c */ #include <stdio.h> int main(void) { float i=0.0; for (i=0.0; i != 1.0; i += 0.1) printf("%f",i); return 0; }
Sicherer ist es, wenn Sie dieses Beispiel so überprüfen:
/* equal_float.c */ #include <stdio.h> int main(void) { float i=0.0; for (i=0.0; i < 0.9999 || i > 1.0001; i += 0.1) printf("%f",i); return 0; }
Hinweis |
Für Vergleiche von reellen Gleitpunktzahlen stehen auch Makros zur Verfügung. Mehr dazu können Sie in Abschnitt 20.3.6, »Makro zum Vergleich mit reellen Zahlen«, nachlesen. |
Hinweis |
Für den Fall, dass sich jemand näher mit der Gleitpunktdarstellung auf verschiedenen Systemen auseinandersetzen will (muss), hier ein Link dazu: http://cch.loria.fr/documentation/IEEE754/numerical_comp_guide/index.html |
Natürlich kann ich jetzt nicht einfach schreiben, dass Sie sich in Acht nehmen sollen, wenn Sie Gleitpunktzahlen für Ihre Berechnungen verwenden, sondern hier wird wohl eine informatiker-gerechte Erklärung nötig sein. Zunächst mal möchte ich Ihnen das Gleitpunktformat beschreiben, das aus einem Vorzeichen, einem Dezimalbruch und einem Exponenten besteht:
+-f.fff x 10+-eZunächst finden Sie mit +- das Vorzeichen, gefolgt vom Dezimalbruch mit den vier Stellen f.fff und am Ende den Exponenten mit einer Stelle (+-e ). Die Zahlen werden gewöhnlich im E-Format (+-f.fffE+-e ) geschrieben. Zwar hat das IEEE das Gleitpunktformat standardisiert, aber leider halten sich nicht alle Computer daran. So wird beispielsweise die Zahl 1.0 wie im E-Format mit +1.000E+0 beschrieben oder –0.006321 mit –6.321E-3 und die 0.0 mit +0.000E+0.
So weit, so gut. Wenn Sie beispielsweise 2 /6 + 2 /6 rechnen, kommen Sie wohl auf das Ergebnis 4 /6. Richtig für Sie, aber hier geht das Dilemma Gleitpunktzahlen und Rundungsfehler schon los. 2 /6 ist im E-Format gleich +3.333E-1. Addieren Sie nun +3.333E-1 mit +3.333E-1, erhalten Sie als Ergebnis +6.666E-1 (bzw. 0.6666). Gut, aber leider falsch, denn 4 /6 sind im E-Format +6.667E-1, aber nicht wie berechnet +6.666E-1. Mit derartigen Rundungsfehlern haben viele Computer ihre Probleme.
Daher schon der erste Ratschlag: Sollten Sie eine Software entwickeln, mit der Geld verwaltet wird, und Sie wollen bzw. können dabei auf keine anderen Bibliotheken bzw. BCD-Arithmetiken zurückgreifen, dann sollten Sie die Beträge niemals im Gleitpunktformat verwenden (hierzulande also niemals mit Euro und Cent wie 1,99 ). Hier empfiehlt es sich, zur Berechnung die Geldbeträge in Cent als Integerzahl zu verwenden, da sonst bei immer intensiveren Berechnungen Rundungsfehler gemacht werden und somit eine falsche Berechnung garantiert ist.
Man kann nicht mal ganz genau sagen, wie genau eine solche gebrochene Zahl ist, weil dies von der Art der Berechnung abhängt. Beispielsweise führen Subtraktionen mehrerer ähnlicher Zahlen zu einem ungenaueren Ergebnis.
Hinweis |
Um sich also mit den Problemen der Gleitpunktzahlen auseinanderzusetzen, müssen Sie sich mit Themen wie »numerischer Analyse« oder BCD-Arithmetik befassen. Allerdings sind dies Themen, die weit über dieses Buch hinausgehen würden. |
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.