Ratgeber · 8 Min Lesezeit

IEEE 754: wie Computer mit Kommazahlen umgehen

Warum 0,1 + 0,2 nicht exakt 0,3 ergibt und wie der IEEE-754-Standard Vorzeichen, Mantisse und Exponent in 32 oder 64 Bit packt.

In jedem Programmierkurs gibt es früher oder später den Aha-Moment: 0.1 + 0.2 == 0.3 ist false. Das Ergebnis ist nicht 0,3, sondern 0,30000000000000004. Wer nach dem Grund sucht, landet beim IEEE-754-Standard, der seit 1985 die Darstellung von Gleitkommazahlen in fast jedem Computer regelt.

Die Grundidee: wissenschaftliche Notation in Binär

Im Alltag schreiben wir große oder sehr kleine Zahlen in wissenschaftlicher Notation: 6,022 × 10²³ statt der ausgeschriebenen Avogadro-Zahl. Drei Komponenten machen das aus: das Vorzeichen, die signifikanten Stellen (die Mantisse 6,022) und der Exponent zur Basis 10.

IEEE 754 tut dasselbe, nur binär:

Wert = (-1)^Vorzeichen × 1,Mantisse × 2^Exponent

Eine Gleitkommazahl ist also kein einzelnes Bitmuster für einen Zahlenwert, sondern ein Tupel aus drei Teilen, die getrennt codiert sind.

Single Precision: 32 Bit

Der häufigste Typ, float in C oder Float32 in Julia, belegt 32 Bit, aufgeteilt in:

BitsBedeutung
1Vorzeichen (0 = positiv, 1 = negativ)
8Exponent (mit Bias 127)
23Mantisse (Nachkommastellen, das führende 1, ist implizit)

Beispiel: die Zahl 5,75 ist binär 101,11. In wissenschaftlicher Form: 1,0111 × 2². Das gibt:

Vorzeichen: 0
Exponent:   127 + 2 = 129 = 10000001
Mantisse:   01110000000000000000000  (die führende 1, ist weggelassen)

Zusammen: 0 10000001 01110000000000000000000, was in Hex 0x40B80000 ergibt. Wer mag, kann das mit Tools wie printf "%a" in C oder Pythons struct.unpack prüfen.

Double Precision: 64 Bit

Für mehr Genauigkeit gibt es Double Precision (double in C, Standard für JavaScript-Zahlen):

BitsBedeutung
1Vorzeichen
11Exponent (Bias 1023)
52Mantisse

Doubles haben rund 15 bis 17 dezimale Stellen Genauigkeit, gegenüber 7 bei single. Sie sind heute der Standard für allgemeine numerische Berechnungen.

Warum 0,1 + 0,2 nicht 0,3 ist

Hier liegt der Kern des Problems. Manche Dezimalbrüche, die im Zehnersystem endlich sind, sind im Binärsystem unendlich. 0,1 dezimal ist binär:

0,000110011001100110011001100110011...  (Periode "0011")

Wenn der Computer 0,1 als Float speichert, muss er irgendwann abschneiden. Es wird also nicht exakt 0,1 gespeichert, sondern der nächstgelegene darstellbare Wert. Bei Double Precision ist das ungefähr 0,1000000000000000055511151231257827021181583404541015625.

Wenn man zwei solche Annäherungen addiert, summieren sich die kleinen Fehler. 0,1 + 0,2 ergibt nicht 0,3, sondern 0,30000000000000004, weil beide Operanden minimal größer als ihre Dezimalwerte gespeichert sind.

Das ist kein Bug, sondern eine fundamentale Eigenschaft binärer Gleitkommadarstellung. Wer Geldwerte oder andere exakte Beträge braucht, sollte deshalb Decimal- oder Integer-Typen (in Cent) verwenden, niemals Float oder Double.

Sonderwerte

IEEE 754 reserviert bestimmte Bitmuster für Sonderfälle:

  • Null: Exponent und Mantisse beide 0. Es gibt eine +0 und eine -0, die beim Vergleich gleich sind.
  • Unendlich: Exponent alle 1, Mantisse 0. 1.0 / 0.0 ergibt +Infinity, -1.0 / 0.0 ergibt -Infinity.
  • NaN (Not a Number): Exponent alle 1, Mantisse ungleich 0. Entsteht bei 0/0, sqrt(-1) oder Infinity - Infinity. Hat die Besonderheit, dass NaN == NaN immer false ist; Vergleich mit isnan() ist Pflicht.
  • Subnormale Zahlen: Exponent 0, Mantisse ungleich 0. Sie erlauben sehr kleine Werte nahe Null, allerdings mit reduzierter Genauigkeit.

Rundung und Genauigkeit

IEEE 754 definiert vier Rundungsmodi, der Standard ist round-half-to-even (auch banker’s rounding). Bei einer Zahl genau zwischen zwei darstellbaren Werten wird zum geraden Ergebnis gerundet. Das mildert systematische Verzerrungen, die beim klassischen kaufmännischen Runden auftreten würden.

Die Genauigkeit ist nicht überall gleich. In der Nähe von Null sind die darstellbaren Werte sehr dicht, bei großen Zahlen weit auseinander. Bei einem Double sind benachbarte Zahlen um 10¹⁵ etwa 0,125 voneinander entfernt; bei 10¹⁶ schon 2. Wer also mit Zahlen jenseits von 2⁵³ rechnet, verliert Ganzzahl-Präzision.

Praktische Konsequenzen

Ein paar Faustregeln, die fast jeden Programmierer einmal überraschen:

  • Geldbeträge nie in Float. Lieber Cent als Integer oder Decimal-Typ mit fester Skalierung.
  • Vergleiche mit Toleranz, nicht direkt: abs(a - b) < epsilon statt a == b.
  • Reihenfolge zählt. (a + b) + c ist nicht immer a + (b + c), weil unterschiedliche Rundungen entstehen.
  • NaN-Checks sind nötig, sobald Inputs unsicher sind.
  • JavaScript-Zahlen sind alle Doubles, auch die scheinbaren Integers. Ab 2⁵³ wird mit Lücken gerechnet, deshalb gibt es BigInt für ganze Zahlen jenseits dieses Bereichs.

Verwandte Themen

Wer die Grundlagen der binären Darstellung auffrischen will: Binär zu Dezimal erklärt den Stellenwert-Ansatz auch für Kommazahlen. Tiefer in die Hardware: Wie Computer rechnen.

Anzeige
Anzeige
Anzeige
Anzeige
Anzeige