neustes

Die stille Unschärfe: Warum IEEE 754 uns täglich belügt – und warum das eigentlich korrekt ist

Von DerSchneider


Einleitung: Der Cent, der verschwindet

Es gibt Momente, in denen die scheinbar perfekte Welt der Computer einen Riss bekommt. Man öffnet die Konsole, tippt eine harmlose Addition ein – 0.1 + 0.2 – und erwartet 0.3. Doch auf dem Bildschirm erscheint: 0.30000000000000004. Ein Fehler, der so winzig ist, dass er im Alltag meist unbemerkt bleibt, aber tief genug reicht, um Finanzsysteme zum Absturz zu bringen oder wissenschaftliche Simulationen zu untergraben. Die Ursache liegt nicht in einem Programmfehler, sondern in einem fundamentalen Kompromiss, den die Informatik vor über vier Jahrzehnten eingegangen ist: dem IEEE-754-Standard für Gleitkommazahlen.

Dieser Artikel beleuchtet, warum diese „falschen“ Ergebnisse keine Fehler im eigentlichen Sinne sind, sondern die logische Konsequenz einer endlichen Maschine, die versucht, unendliche mathematische Räume abzubilden. Es ist eine Geschichte von Ingenieurskunst, historischen Machtkämpfen und der Erkenntnis, dass Perfektion manchmal darin besteht, die Grenzen des Möglichen präzise zu definieren.

Der Kompromiss: Unendlichkeit im endlichen Speicher

Das grundlegende Dilemma ist so einfach wie unausweichlich: Die Menge der reellen Zahlen ist unendlich, der Speicher eines Computers ist es nicht. Ein 64-Bit-Double kann theoretisch 264264 verschiedene Werte darstellen – eine gewaltige Zahl, aber dennoch endlich. Die reellen Zahlen hingegen füllen selbst das kleinste Intervall lückenlos aus. Irgendwo muss also geschnitten werden.

IEEE 754 löst dieses Problem durch ein Format, das einer wissenschaftlichen Notation ähnelt: Eine Zahl wird als Vorzeichen, Mantisse (Signifikand) und Exponent gespeichert. Der Wert ergibt sich aus (−1)s×1.m×2e−bias(−1)s×1.m×2e−bias. Der entscheidende Punkt ist die Länge der Mantisse: Bei einem Double sind es 52 Bit (plus ein implizites Bit), was etwa 15 bis 17 signifikanten Dezimalstellen entspricht .

Diese endliche Mantisse ist der Ursprung allen Übels – oder genauer: der Unschärfe. Denn nur Zahlen, die sich als endliche Summe von Zweierpotenzen darstellen lassen, finden exakt Platz in diesem Raster. Die Dezimalzahl 0.1 gehört nicht dazu.

Binäre Perioden: Warum 0.1 nicht 0.1 ist

In der Schule lernt man, dass Brüche wie 1/31/3 im Dezimalsystem nicht enden wollen: 0.333…. Dasselbe Phänomen tritt im Binärsystem bei vielen Dezimalbrüchen auf, die uns alltäglich erscheinen. Die Umrechnung von 0.1 ins Binäre erfolgt durch wiederholtes Multiplizieren mit 2 und Abspalten des ganzzahligen Anteils. Das Ergebnis ist eine periodische Folge: 0.00011001100110011… .

Weil die Mantisse nach 52 Bit abschneidet (und dabei rundet), wird nicht 0.1 gespeichert, sondern der nächstgelegene darstellbare Wert – eine Zahl, die um etwa 5.55×10−185.55×10−18 danebenliegt . Jede einzelne Gleitkommazahl repräsentiert also nur sich selbst, nicht ein Intervall um einen „wahren“ Wert . Diese Erkenntnis ist zentral: Der Fehler entsteht nicht durch unsaubere Programmierung, sondern durch die Repräsentation selbst.

Die Akkumulation: Warum ein kleiner Fehler groß wird

Ein einzelner Rundungsfehler von 10−1710−17 ist für praktisch alle Anwendungen irrelevant. Das Problem ist die Fortpflanzung. Jede arithmetische Operation – Addition, Subtraktion, Multiplikation, Division – wird nach IEEE 754 korrekt gerundet, das heißt, das Ergebnis ist der nächstgelegene darstellbare Wert zum exakten mathematischen Resultat . Doch diese Rundung findet bei jeder Operation statt.

Addiert man 0.1 und 0.2, werden zwei bereits gerundete Werte addiert, und das Ergebnis wird erneut gerundet. Die Fehler addieren sich. In einer Schleife, die tausendmal 0.1 aufsummiert, akkumuliert sich der Fehler zu sichtbaren Abweichungen: Statt 100 erhält man 99.9999999999986 .

Noch dramatischer ist die Auslöschung (Cancellation). Subtrahiert man zwei fast gleiche Zahlen, deren Differenz klein ist, bleiben von den signifikanten Stellen nur wenige übrig – die führenden Stellen heben sich auf, und der relative Fehler explodiert. Die ETH Zürich warnt in ihren Informatikvorlesungen explizit davor, zwei Zahlen mit sehr ähnlichem Wert zu subtrahieren .

Ein weiteres Phänomen ist die Verschluckung kleiner Zahlen: Addiert man eine sehr kleine Zahl zu einer sehr großen, kann die kleine vollständig aus der Mantisse fallen. 1e16 + 1 ergibt in doppelter Genauigkeit exakt 1e16, weil die 1 unterhalb der Auflösungsschwelle liegt.

Die historische Dimension: Vom Chaos zum Standard

So selbstverständlich uns IEEE 754 heute erscheint, so chaotisch war die Zeit davor. In den 1970er Jahren hatte jeder Hersteller seine eigene Gleitkomma-Arithmetik. Programme, die auf einer Maschine liefen, konnten auf einer anderen völlig andere Ergebnisse liefern – oder abstürzen. Die Portabilität numerischer Software war ein Albtraum .

Die Geschichte des Standards ist eng mit dem Namen William Kahan verbunden, der 1989 den Turing Award für seine Arbeit an der numerischen Analyse erhielt. Kahan und eine kleine Gruppe von Mitstreitern – Jerome Coonen, Harold Stone, Tom Pittman und David Palmer – entwarfen in den späten 1970er Jahren den Entwurf, der 1985 als IEEE 754 verabschiedet wurde . Der Standard definierte nicht nur das Format, sondern auch das Rundungsverhalten (round to nearest, ties to even), Sonderwerte wie Infinity und NaN sowie fünf Ausnahmeklassen (Overflow, Underflow, Division durch Null, ungültige Operation, ungenau) .

Interessant ist, dass der Standard seither mehrfach überarbeitet wurde. Die Version von 2008 brachte Dezimalformate und den Fused Multiply-Add (FMA), der Multiplikation und Addition in einem Schritt mit nur einer Rundung ausführt. Die aktuell gültige Version ist IEEE 754-2019, eine vergleichsweise bescheidene Überarbeitung mit Fehlerkorrekturen .

Jenseits des Offensichtlichen: Kontroversen und Grenzen

IEEE 754 ist nicht unumstritten. Ein wiederkehrender Kritikpunkt betrifft die Erweiterte Präzision auf x86-Prozessoren. Die x87-FPU rechnete intern mit 80 Bit, während double nur 64 Bit hat. Das konnte dazu führen, dass ein Programm auf einem System „Equal“ ausgab und auf einem anderen „Not Equal“, je nachdem, ob ein Zwischenergebnis im Register (80 Bit) verblieb oder in den Speicher (64 Bit) geschrieben wurde . Der C-Standard und IEEE 754 ringen bis heute um den Umgang mit solchen Zwischenpräzisionen.

Ein anderer Punkt ist die Nicht-Assoziativität der Gleitkomma-Arithmetik. Dass (a + b) + c nicht dasselbe ergeben muss wie a + (b + c), ist für Mathematiker eine Provokation, für Numeriker Alltag. Die Reihenfolge der Operationen beeinflusst das Ergebnis, was Optimierungen durch Compiler erschwert und die Reproduzierbarkeit von Ergebnissen über verschiedene Hardware hinweg infrage stellt .

Schließlich die Frage der Glaubwürdigkeit: Der Standard garantiert, dass eine einzelne Operation korrekt gerundet ist, aber er garantiert nicht, dass eine komplexe Berechnung „genau genug“ ist. Die Fehlerfortpflanzung durch viele Operationen kann dazu führen, dass von 15 signifikanten Stellen am Ende nur noch zwei übrig sind. Die Verantwortung, die Kondition eines Problems zu analysieren und geeignete Algorithmen zu wählen, bleibt beim Entwickler .

Praktische Konsequenzen: Was tun?

Die Einsicht in die Natur der Gleitkomma-Arithmetik führt zu konkreten Regeln. Für Geldbeträge sollte man niemals float oder double verwenden, sondern Ganzzahlen (Cent) oder dezimale Gleitkommatypen wie decimal in Python oder BigDecimal in Java. Für Vergleiche gilt: == ist tabu; stattdessen prüft man, ob die Differenz unterhalb einer Toleranz liegt.

Für Summen vieler Zahlen bietet sich die Kahan-Summation an, die einen separaten Kompensationslauf mitführt, um verlorene niederwertige Bits wieder einzufangen. Der Worst-Case-Fehler wächst dann nicht mehr linear mit der Anzahl der Summanden, sondern bleibt nahezu konstant . In der Praxis reicht oft schon die Wahl des richtigen Datentyps: Wer mit double statt float rechnet, gewinnt etwa neun Dezimalstellen Genauigkeit.

Fazit: Die Ehrlichkeit der Endlichkeit

Die „falschen“ Ergebnisse von Gleitkomma-Berechnungen sind keine Fehler, sondern die ehrliche Antwort einer endlichen Maschine auf eine unendliche Frage. IEEE 754 hat das Beste aus diesem Dilemma gemacht: Es hat einen präzisen, reproduzierbaren und weitgehend vernünftigen Kompromiss definiert, der seit fast vier Jahrzehnten die Grundlage praktisch aller numerischen Berechnung bildet.

Wer versteht, dass 0.1 im Binärsystem eine unendliche Periode hat, wer weiß, dass jede Operation rundet und dass Fehler sich akkumulieren können, ist besser gerüstet als jener, der blind auf die vermeintliche Präzision der Maschine vertraut. Die stille Unschärfe ist kein Bug – sie ist eine Einladung, die Grenzen des eigenen Werkzeugs zu kennen und respektvoll mit ihnen umzugehen.


Kategorien: im-kopf, denkwerkzeuge

Schlagworte: IEEE 754, Gleitkomma-Arithmetik, Rundungsfehler, Numerische Stabilität, Binäre Repräsentation, Kahan-Summation, Auslöschung


Quellen

  1. Goldberg, David. „What Every Computer Scientist Should Know About Floating-Point Arithmetic.“ ACM Computing Surveys, Bd. 23, Nr. 1, 1991. (Online verfügbar u. a. unter den Dokumentationsseiten von Oracle und University of Toronto)
  2. IEEE. IEEE Standard for Floating-Point Arithmetic, IEEE 754-2019. IEEE Standards Association, 2019.
  3. Kahan, William. „IEEE Standard 754 for Binary Floating-Point Arithmetic.“ Lecture Notes, University of California, Berkeley, 1997.
  4. Severance, Charles. „The IEEE Standard 754: One for the History Books.“ Computer, Bd. 52, Nr. 12, Dezember 2019, S. 109–112.
  5. ETH Zürich. „Floating-point Numbers II.“ Vorlesungsfolien Informatik I, 2017.
  6. Oracle. „What Every Computer Scientist Should Know About Floating-Point Arithmetic – Appendix D.“ In: Numerical Computation Guide.
  7. Kahan, William. „Kahan Summation Algorithm.“ Konzeptbeschreibung, EPFL Graph Search.

Post Comment

You May Have Missed