Wie ein Float gespeichert wird
IEEE 754 speichert eine Zahl als Vorzeichen × 1.Fraktion × 2Exponent, also in binärer wissenschaftlicher Notation. Ein 32-Bit-Float hat 1 Vorzeichenbit, 8 Exponentenbits und 23 Fraktionsbits; ein 64-Bit-Double hat 1, 11 und 52. Der Exponent wird mit einem Bias (127 oder 1023) gespeichert, damit er kein eigenes Vorzeichenbit braucht, und die führende 1 der Mantisse wird gar nicht gespeichert, weil sie bei normalen Zahlen immer da ist.
| Vorzeichen | Exponent | Fraktion | Bias | Dezimalstellen | |
|---|---|---|---|---|---|
| float32 (binary32) | 1 | 8 | 23 | 127 | ~7 |
| float64 (binary64) | 1 | 11 | 52 | 1023 | ~16 |
Warum 0.1 + 0.2 nicht 0.3 ist
0.1 hat keine endliche Binärentwicklung, so wie 1/3 keine im Dezimalsystem hat. Der nächste float64 ist 0,1000000000000000055511151231257827…, und 0.2 und 0.3 liegen ebenfalls leicht daneben. Die beiden gerundeten Werte addieren und erneut runden landet eine Einheit neben dem Float, der 0.3 am nächsten ist, deshalb schlägt der Vergleich fehl. Geben Sie oben 0.1 ein und sehen Sie sich die Zeile „exakt gespeicherter Wert“ an, um die Rundung direkt zu sehen.
Besondere Muster
- Null: Exponent und Fraktion ganz 0. Das Vorzeichenbit zählt trotzdem, also gibt es −0, das in Vergleichen gleich +0 ist.
- Subnormal: Exponent ganz 0, Fraktion ungleich null. Das sind winzige Werte unterhalb des normalen Bereichs, mit reduzierter Genauigkeit und ohne implizite führende 1.
- Unendlich: Exponent ganz 1, Fraktion 0. Entsteht durch Überlauf und Division durch null.
- NaN: Exponent ganz 1, Fraktion ungleich null. Entsteht durch 0/0, ∞−∞, sqrt(−1). NaN ist mit nichts gleich, auch nicht mit sich selbst.
Die Bits von Hand lesen
- Das Muster in die Felder Vorzeichen, Exponent und Fraktion aufteilen.
- Den Bias vom Exponenten abziehen, um die tatsächliche Zweierpotenz zu erhalten.
- „1.“ vor die Fraktionsbits setzen (oder „0.“ bei subnormalen Zahlen) und mit 2 hoch dieser Potenz multiplizieren.
Für 0x40490FDB: Vorzeichen 0, Exponent 10000000 = 128 → 128 − 127 = 1, Fraktion 1.1001001000011111101101 → 1,5707963 × 2 = 3,1415927, der float32, der π am nächsten kommt.
Fragen
Was ist der Unterschied zwischen float und double?
Ein float (float32) nutzt 32 Bit und bietet etwa 7 signifikante Dezimalstellen; ein double (float64) nutzt 64 Bit und bietet etwa 16. Doubles sind in den meisten Sprachen der Standard (JavaScript-Zahlen, Python-Floats, C double); Floats werden verwendet, wo Speicher oder GPU-Bandbreite zählen.
Warum nutzt der Exponent einen Bias statt des Zweierkomplements?
Mit einem Bias lassen sich Floats gleichen Vorzeichens korrekt als einfache Ganzzahlen vergleichen: Ein größeres Bitmuster ist eine größere Zahl. Das macht Sortieren und Vergleichen in Hardware billig.
Was ist das Maschinen-Epsilon?
Der Abstand zwischen 1,0 und dem nächsten darstellbaren Float: 2⁻²³ ≈ 1,19 × 10⁻⁷ für float32 und 2⁻⁵² ≈ 2,22 × 10⁻¹⁶ für float64. Der Abstand wächst mit der Größe der Zahl: Ab 2²⁴ kann ein float32 keine ungeraden Ganzzahlen mehr darstellen.
Was ist die größte Ganzzahl, die ein double exakt speichern kann?
2⁵³ = 9.007.199.254.740.992. Darüber sind nicht mehr alle aufeinanderfolgenden Ganzzahlen darstellbar, weshalb JavaScript Number.MAX_SAFE_INTEGER (2⁵³ − 1) und BigInt hat.
Warum gibt meine Sprache 0.30000000000000004 aus?
Weil das die kürzeste Dezimalzahl ist, die den double aus 0.1 + 0.2 eindeutig bezeichnet. Die Ausgabe ist korrekt; der gespeicherte Wert ist es, der sich von 0.3 unterscheidet.