IEEE-754-Bitmuster-Visualisierer für Gleitkommazahlen
Zerlegt eine Dezimalzahl in ihr IEEE-754-Bitmuster mit einfacher Genauigkeit (32 Bit) oder doppelter Genauigkeit (64 Bit), oder decodiert ein Bitmuster zurück in einen Dezimalwert. Vorzeichen, Exponent und Mantisse werden farblich unterschieden dargestellt, mit Unterstützung für NaN, Unendlich und subnormale Zahlen.
Das klassische Beispiel: Warum 0.1 + 0.2 nicht 0.3 ergibt
In JavaScript ergibt `0.1 + 0.2` den Wert `0.30000000000000004`, nicht `0.3`. Ein Blick auf die Bitmuster mit doppelter Genauigkeit erklärt, warum.
| Wert | Hexadezimal mit doppelter Genauigkeit (64 Bit) | Binär mit doppelter Genauigkeit (64 Bit) |
|---|---|---|
| 0.1 | 0x3FB999999999999A | 0011111110111001100110011001100110011001100110011001100110011010 |
| 0.2 | 0x3FC999999999999A | 0011111111001001100110011001100110011001100110011001100110011010 |
| 0.3 | 0x3FD3333333333333 | 0011111111010011001100110011001100110011001100110011001100110011 |
| 0.1 + 0.2 | 0x3FD3333333333334 | 0011111111010011001100110011001100110011001100110011001100110100 |
0.1, 0.2 und 0.3 sind im Binärsystem allesamt unendlich periodische Brüche, sodass keiner von ihnen exakt in die 52-Bit-Mantisse passt und jeder gerundet wird. Da sich die Rundungsfehler von 0.1 und 0.2 nicht zufällig gegenseitig aufheben, weicht ihre Summe am Ende genau ein Bit vom exakten Bitmuster für 0.3 (0x3FD3333333333334) ab. Geben Sie diese Werte oben in den Konverter ein und vergleichen Sie die abschließenden Bits selbst.
Tipps
- Wandeln Sie 0.1, 0.2 und 0.3 mit doppelter Genauigkeit in Bits um und vergleichen Sie sie mit dem Ergebnis von 0.1+0.2 (0.30000000000000004) — Sie können optisch erkennen, dass sich nur das letzte Bit unterscheidet.
- Die Eingabe von „-0“ im Dezimalfeld erzeugt ein Bitmuster, bei dem nur das Vorzeichenbit gesetzt ist (anders als bei „+0“). Als Zahlen gilt 0 === -0, aber die Bitdarstellungen sind unterschiedlich.
- Wenn das Exponentenfeld vollständig null ist, bedeutet eine Mantisse von null tatsächlich null, und eine Mantisse ungleich null bedeutet eine subnormale Zahl — eine spezielle Darstellung, mit der Werte extrem nahe null auf Kosten der Genauigkeit erreicht werden.
- Das Umschalten zwischen einfacher (32 Bit) und doppelter (64 Bit) Genauigkeit für denselben Wert wie 0.1 zeigt, dass der Rundungsfehler bei einfacher Genauigkeit größer ist.
- Um ein Bitmuster zurück in einen Dezimalwert zu decodieren, geben Sie entweder eine mit `0x` versehene Hexadezimalzeichenfolge oder eine Binärzeichenfolge mit genau so vielen Stellen wie die gewählte Genauigkeit ein (das Präfix `0b` ist optional).
Häufig gestellte Fragen
Übrigens – Wie IEEE 754 zu einer gemeinsamen Sprache wurde
Vor 1985 verwendete jeder Computerhersteller seine eigene Gleitkommadarstellung. IBM, DEC, Cray und andere konnten denselben Wert, etwa „0.1“, berechnen und dabei subtil unterschiedliches Rundungsverhalten und darstellbare Wertebereiche erhalten, sodass das Portieren eines numerischen Programms von einer Maschine auf eine andere oft leicht unterschiedliche Ergebnisse lieferte. Um dieses Chaos zu beheben, trieb eine Arbeitsgruppe unter der Leitung von William Kahan von der UC Berkeley — der auch am Design des numerischen Koprozessors Intel 8087 mitgewirkt hatte — die Schaffung eines branchenweiten Standards voran, der 1985 als IEEE 754 veröffentlicht wurde.
Die Kernidee von IEEE 754 besteht darin, eine endliche Anzahl von Bits (32 oder 64) in drei Rollen aufzuteilen — Vorzeichen, Exponent und Mantisse —, um die unendliche Menge der reellen Zahlen anzunähern. Der Exponent übernimmt die Skalierung (wie groß oder klein eine Zahl ist), während die Mantisse die Genauigkeit übernimmt (wie viele signifikante Stellen sie hat), sodass eine feste Anzahl von Bits flexibel sowohl sehr kleine als auch sehr große Größenordnungen abdecken kann. Der Exponent wird mit einem addierten Bias gespeichert (127 bei einfacher, 1023 bei doppelter Genauigkeit), sodass der einfache Vergleich zweier Bitmuster als vorzeichenlose Ganzzahlen genügt, um zu bestimmen, welcher Wert größer ist — und die zusätzliche Komplexität einer vorzeichenbehafteten Darstellung wie des Zweierkomplements vermieden wird.
Nur Brüche, deren Nenner eine Zweierpotenz ist (1/2, 1/4, 3/8 und so weiter), lassen sich binär exakt darstellen. Der Dezimalwert 0.1 ist der Bruch 1/10, und da 10 keine Zweierpotenz ist, wird er zum unendlich periodischen Binärbruch 0.0001100110011... Mit nur einer endlichen Anzahl verfügbarer Mantissenbits muss er irgendwo abgeschnitten und gerundet werden — das ist der grundlegende Grund, warum ein Computer 0.1 nicht exakt darstellen kann. Aus demselben Grund vermeiden Buchhaltungssysteme, die eine exakte Dezimalarithmetik benötigen, in der Regel Gleitkommazahlen zugunsten von Ganzzahlarithmetik oder eines dedizierten Dezimaltyps (wie BCD).
IEEE 754 wurde später 2008 und 2019 überarbeitet und um halbe Genauigkeit (16 Bit), vierfache Genauigkeit (128 Bit) und dezimale Gleitkommaformate erweitert, aber die grundlegende Dreiteilung in Vorzeichen, Exponent und Mantisse sowie die Rundungsmodi sind seit der ursprünglichen Ausgabe von 1985 unverändert geblieben. Da nahezu jeder float/double-Typ jeder Programmiersprache diesem Standard entspricht, taucht die Frage „Warum ist 0.1 + 0.2 nicht gleich 0.3?“ unabhängig von der verwendeten Sprache im Wesentlichen in derselben Form auf.