Umfassender Leitfaden zum Verständnis von IEEE-Gleitkommafehlern

SPRACHE AUSWÄHLEN SPRACHE AUSWÄHLEN
Artikel-ID: 42980 - Produkte anzeigen, auf die sich dieser Artikel bezieht
Dieser Artikel wurde zuvor veröffentlicht unter D44053
Dieser Artikel ist eine Übersetzung des folgenden englischsprachigen Artikels der Microsoft Knowledge Base:
42980 Titel des Originalartikels: (Complete) Tutorial to Understand IEEE Floating-Point Errors
Alles erweitern | Alles schließen

Auf dieser Seite

Zusammenfassung

Die Gleitkommamathematik ist ein äußerst komplexes Thema, das bei vielen Programmierern Verunsicherung erzeugt. Der folgende Leitfaden soll Ihnen helfen, Situationen beim Programmieren zu erkennen, in denen mit einer gewissen Wahrscheinlichkeit Gleitkommafehler auftreten können. Zudem erfahren Sie, wie Sie derartige Fehler vermeiden können. So lernen Sie auch, zwischen Fällen inhärenter Beschränkungen in Bezug auf die Gleitkommamathematik und tatsächlichen Kompilierfehlern zu unterscheiden.

Weitere Informationen

Dezimal- und Binärsystem:
Normalerweise legen wir beim Zählen von Dingen die Basis 10 zu Grunde. Diese Wahl der Basis 10 ist eigentlich völlig willkürlich. Ein einleuchtender Grund für ihre traditionelle Verwendung ist, dass wir zehn Finger haben, die wir ständig als Zählhilfen "zur Hand" haben.

Die Zahl 532,25 im Dezimalsystem (Basis 10) hat die folgenden Bedeutung:
   (5 * 10^2) + (3 * 10^1) + (2 * 10^0) + (2 * 10^-1) + (5 * 10^-2)
       500    +     30     +      2     +     2/10    +    5/100
   _________
   =  532,25
Im Binärsystem (Basis 2) repräsentiert jede Spalte eine Potenz von 2 statt einer Zehnerpotenz. So hat zum Beispiel die Zahl 101.01 im Binärsystem die folgende Bedeutung:
   (1 * 2^2) + (0 * 2^1) + (1 * 2^0) + (0 * 2^-1) + (1 * 2^-2)
       4     +      0    +     1     +      0     +    1/4
   _________
   =  5,25  (dezimal)
Darstellung ganzer Zahlen durch PCs:
Da es bei einer ganzen Zahl keine gebrochenen Bestandteile gibt, ist ihre Darstellung wesentlich einfacher als die von Gleitkommawerten. Normale ganze Zahlen sind auf Personalcomputern (PCs) 2 Byte (16 Bit) lang, wobei das wichtigere Bit das Vorzeichen bestimmt. Lange ganze Zahlen sind 4 Byte lang. Positive Werte sind einfach strukturierte Binärzahlen. Zum Beispiel:
    1 dezimal = 1 binär
    2 dezimal = 10 binär
   22 dezimal = 10110 binär, etc.
Bei negativen ganzen Zahlen wird hingegen das Zweierkomplementschema verwendet. Um zu der Zweierkomplementdarstellung einer negativen Zahl zu gelangen, nehmen Sie die binäre Darstellung für den Absolutwert der Zahl, spiegeln alle Bits und fügen dann 1 hinzu. Zum Beispiel:
   4 dezimal = 0000 0000 0000 0100
               1111 1111 1111 1011     Bits spiegeln
   -4        = 1111 1111 1111 1100     1 hinzufügen
Beachten Sie bitte, dass -1 Dezimal = 1111 1111 1111 1111 im Binärsystem ist, was erklärt, warum Basic -1 als logisch wahr behandelt (alle Bits = 1). Dies ist eine Konsequenz daraus, dass es keine separaten Operatoren für bitweise und logische Vergleiche gibt. In Basic ist es oft empfehlenswert, das folgende Codefragment zu verwenden, wenn Ihr Programm logische Vergleiche ausführen soll. Dadurch wird die Lesbarkeit erheblich verbessert.
   CONST TRUE = -1
   CONST FALSE = NOT TRUE
Beachten Sie bitte, dass bei der Addition zweier Zweierkomplementzahlen unter Verwendung normaler binärer Arithmetik das Resultat korrekt ist.

Komplikationen bei der Gleitkommarechnung:
Jede dezimale ganze Zahl kann durch eine binäre ganze Zahl dargestellt werden; dies gilt jedoch nicht für gebrochene Zahlen. Tatsächlich wird jede Zahl, die im Dezimalsystem irrational ist, auch bei einer Basis kleiner als 10 irrational sein.

Für Binärzahlen gilt insbesondere, dass nur gebrochene Zahlen, die in der Form p/q (wobei q eine ganzzahlige Potenz von 2 ist) dargestellt werden können, exakt mit einer endlichen Anzahl an Bits ausgedrückt werden können.

Selbst gewöhnliche dezimale Brüche, wie die Dezimalzahl 0,0001, können nicht exakt als Binärzahl dargestellt werden. (0,0001 ist ein sich wiederholender (periodischer) binärer Bruch mit einer Periode von 104 Bits!)

Nehmen wir das folgende einfache Beispiel
   SUM = 0
   FOR I% = 1 TO 10000
      SUM = SUM + 0.0001
   NEXT I%
   PRINT SUM                   ' Theoretisch = 1,0.
bei dem das AUSGEDRUCKTE Ergebnis 1,000054 lautet. Diese kleine Abweichung bei der Darstellung von 0,0001 im Binärsystem kann bei Additionen einen erheblichen Einfluss auf die Gesamtsumme haben.

Aus demselben Grund sollten Sie bei Vergleichen reeller Zahlen immer sehr vorsichtig sein. Das folgende Beispiel illustriert einen häufigen Programmierfehler:
   item1# = 69.82#
   item2# = 69.20# + 0.62#
   IF item1# = item2# then print "Equality!"
Das DRUCKERGEBNIS wird in diesem Fall eben nicht "gleich" sein, weil 69,82 im Binärsystem nicht exakt dargestellt werden kann, was dazu führt, dass der Wert (im Binärsystem) etwas von dem Wert abweicht, der durch den Ausdruck der Funktion generiert wird. In der Praxis sollten Sie solche Vergleiche immer so codieren, dass Raum für gewisse Toleranzen besteht. Zum Beispiel:
   IF (item1# < 69.83#) AND (item1# > 69.81#) then print "Equal"
Hier ist der AUSGEDRUCKTE Wert "gleich" (Equal).

Zahlen im IEEE-Format:
QuickBasic für MS-DOS, Version 3.0, wurde in einer MBF-Version (Microsoft Binary Floating Point) und einer IEEE-Version (IEEE= Institute of Electrical and Electronics Engineers) für Computer mit einem mathematischen Coprozessor ausgeliefert. QuickBasic für MS-DOS (Versionen 4.0 und höher) verwendet ausschließlich IEEE. Microsoft hat sich bei der Darstellung von Gleitkommawerten in den aktuellen Versionen von Basic aus den folgenden drei Hauptgründen für die IEEE-Norm entschieden:
  1. Damit Basic mit mathematischen Coprozessoren von Intel arbeiten kann, die das IEEE-Format verwenden. Die Intel-Coprozessoren der Baureihe 80x87 können keine Zahlen im Microsoft-Binärformat verarbeiten.
  2. Um programmiersprachenübergreifende Aufrufe zwischen Basic, C, Pascal, FORTRAN und MASM wesentlich zu erleichtern. Andernfalls müssten Konvertierungsroutinen eingesetzt werden, um numerische Werte von einer Programmiersprache in eine andere zu übertragen.
  3. Um die Konsistenz zu gewährleisten. IEEE ist der allgemein akzeptierte Standard für C- und FORTRAN-Kompilierprogramme.
Nachstehend sehen Sie einen Vergleich der IEEE- und MBF-Darstellungen einer Zahl mit doppelter Genauigkeit:
           Vorzeichen-Bits   Exponenten-Bits   Mantissen-Bits
IEEE 1 11 52 + 1 (implizit)
    MBF    1                  8                56
Weitere Informationen zu den Unterschieden zwischen der IEEE- und der MBF-Gleitkommadarstellung finden Sie in der Microsoft Knowledge Base, wenn Sie nach folgenden Begriffen suchen:
   IEEE; floating; point; appnote
Beachten Sie bitte, dass bei IEEE mehr Bits auf den Exponenten entfallen, wodurch ein breiterer Bereich von Werten dargestellt werden kann. MBF hat mehr Mantissen-Bits, was in einem engeren Bereich eine größere Präzision ermöglicht.

Allgemeine Gleitkommakonzepte:
Es ist sehr wichtig, sich vor Augen zu führen, dass jedes binäre Gleitkommasystem nur eine endliche Anzahl an Gleitkommawerten exakt darstellen kann. Alle anderen Werte sind Näherungswerte in Form des darstellbaren Wertes, der dem ursprünglichen Wert am nächsten liegt. Der IEEE-Standard spezifiziert das Verfahren zur Rundung von Werten auf den "nächstliegenden" darstellbaren Wert. QuickBasic für MS-DOS unterstützt diesen Standard und rundet den IEEE-Regeln entsprechend.

Beachten Sie bitte auch, dass die Zahlen, die im IEEE-Format dargestellt werden können, einen sehr breiten Bereich abdecken. Sie können sich diese auf einer Art Zahlenlinie vorstellen. Nahe 1,0 und -1,0 gibt es eine hohe Dichte darstellbarer Zahlen, die jedoch immer mehr abnimmt, je mehr Sie sich 0 oder unendlich nähern.

Das Ziel des für technische Berechnungen entwickelten IEEE-Standards ist eine maximale Genauigkeit (bestmögliche Annäherung an die tatsächliche Zahl). Genauigkeit bezieht sich hier auf die Anzahl der darstellbaren Stellen hinter dem Komma. Der IEEE-Standard versucht, eine Balance zwischen der Anzahl der Bits für den Exponenten und der Anzahl an Bits herzustellen, die der Darstellung des gebrochenen Teils einer Zahl dienen, um Präzision und Genauigkeit innerhalb akzeptabler Grenzen zu halten.

IEEE-Details:
Gleitkommazahlen werden in der folgenden Form dargestellt, wobei [Exponent] für den binären Exponenten steht:
   X =  Bruch * 2^(Exponent - Abweichung)
[Bruch] steht für den normalisierten gebrochenen Teil der Zahl; normalisiert, weil der Exponent so angepasst wird, dass das führende Bit immer gleich ist.
  1. So muss dieses Bit nicht gespeichert werden, Ihnen steht also ein Bit mehr für die Genauigkeit zur Verfügung. Aus diesem Grund gibt es ein implizites Bit. Sie können sich dies wie bei der wissenschaftlichen Notation vorstellen, bei der Sie den Exponenten so manipulieren, dass Sie eine Stelle links vom Komma erhalten. Im Binärsystem können Sie den Exponenten immer so manipulieren, dass das erste Bit eine 1 ist, da es nur Einsen und Nullen gibt.
[Abweichung] ist der Abweichungswert, der verwendet wird, um die Notwendigkeit zur Speicherung negativer Exponenten zu umgehen.

Die Abweichung für Zahlen mit einfacher Genauigkeit ist 127 und für Zahlen mit doppelter Genauigkeit (zwei Stellen hinter dem Komma) beträgt sie 1023 (dezimal).

Nur aus Nullen oder nur aus Einsen (binär) bestehende Werte sind für die Darstellung von Sonderfällen reserviert. Es gibt noch weitere Sonderfälle, die auf diverse Fehlerbedingungen hindeuten.

Beispiele für Zahlen mit einfacher Genauigkeit:

2 = 1 * 2^1 = 0100 0000 0000 0000 ... 0000 0000 = 4000 0000 hex

Beachten Sie bitte, dass das Vorzeichen-Bit null ist und der gespeicherte Exponent 128, oder 100 0000 0 im Binärsystem, was 127 plus 1 entspricht. Die gespeicherte Mantisse ist (1.) 000 0000 ... 0000 0000 mit einer impliziten führenden 1 und binärem Punkt, so dass die tatsächliche Mantisse 1 ist.

-2 = -1 * 2^1 = 1100 0000 0000 0000 ... 0000 0000 = C000 0000 hex

Wie bei +2, nur dass hier das Vorzeichen-Bit gesetzt ist. Dies gilt für alle Gleitkommazahlen im IEEE-Format.

4 = 1 * 2^2 = 0100 0000 1000 0000 ... 0000 0000 = 4080 0000 hex

Dieselbe Mantisse, der Exponent erhöht sich um 1 (Abweichungswert 129 oder 100 0000 1 im Binärsystem).

6 = 1,5 * 2^2 = 0100 0000 1100 0000 ... 0000 0000 = 40C0 0000 hex

Derselbe Exponent, die Mantisse ist um 0,5 größer -- also (1.) 100 0000 ... 0000 0000, was, weil es sich hier um einen binären Bruch handelt, 1-1/2 ist (die Werte für gebrochene Stellen sind 1/2, 1/4, 1/8, etc.).

1 = 1 * 2^0 = 0011 1111 1000 0000 ... 0000 0000 = 3F80 0000 hex

Derselbe Exponent wie bei anderen Potenzen von 2, die Mantisse ist eins weniger als 2 bei 127, oder 011 1111 1 im Binärsystem.

0,75 = 1,5 * 2^-1 = 0011 1111 0100 0000 ... 0000 0000 = 3F40 0000 hex

Der Exponent mit eingerechneter Abweichung ist 126, 011 1111 0 im Binärsystem, und die Mantisse ist (1.) 100 0000 ... 0000 0000, was 1-1/2 entspricht.

2,5 = 1,25 * 2^1 = 0100 0000 0010 0000 ... 0000 0000 = 4020 0000 hex

Exakt wie 2, nur dass das Bit, das 1/4 repräsentiert, in der Mantisse gesetzt ist.

0,1 = 1,6 * 2^-4 = 0011 1101 1100 1100 ... 1100 1101 = 3DCC CCCD hex

1/10 ist im Binärsystem ein sich wiederholender (periodischer) Bruch. Die Mantisse liegt nur knapp unter 1,6 und der Exponent mit eingerechneter Abweichung besagt, dass 1,6 durch 16 dividiert werden soll (011 1101 1 im Binärsystem, was im Dezimalsystem 123 ist). Der wirkliche Exponent ist 123 - 127 = -4, was bedeutet, dass der Faktor, mit dem multipliziert werden muss, 2**-4 = 1/16 ist. Beachten Sie bitte, dass die gespeicherte Mantisse in ihrem letzten Bit aufgerundet ist. Dies ist ein Versuch, die eigentlich nicht darstellbare Zahl so exakt wie möglich darzustellen. (Der Grund dafür, dass 1/10 und 1/100 im Binärsystem nicht exakt dargestellt werden können, ähnelt der Ursache dafür, dass 1/3 im Dezimalsystem nicht exakt dargestellt werden kann.)

0 = 1,0 * 2^-128 = nur Nullen - ein Sonderfall.

Sonstige häufig auftretende Gleitkommafehler:
  1. Abrundungsfehler
Dieser Fehler tritt auf, wenn alle Bits in einer binären Zahl nicht in einer Berechnung verwendet werden können.

Beispiel:

Hinzuaddieren von 0,0001 zu 0,9900 (einfache Genauigkeit)

Die Dezimalzahl 0,0001 wird dargestellt als:
   (1.)10100011011011100010111 * 2^(-14+Abweichung) (13 führende Nullen im Binärsystem!)
0,9900 wird dargestellt als:
   (1.)11111010111000010100011 * 2^(-1+Abweichung)
Um diese Zahlen jetzt tatsächlich zu addieren, müssen die dezimalen (binären) Punkte ausgerichtet werden. Hierzu müssen sie denormalisiert werden. Die daraus resultierende Addition sieht wie folgt aus:
       .000000000000011010001101 * 2^0  <- Nur 11 von 23 Bits werden beibehalten
      +0,111111010111000010100011 * 2^0
      ________________________________
       0,111111010111011100110000 * 2^0
Man bezeichnet dies als Abrundungsfehler, weil manche Computer beim Verschieben zwecks Addition runden, während andere Computer die Zahlen einfach abschneiden. Abrundungsfehler sind besonders dann zu berücksichtigen, wenn zwei sehr verschiedene Werte addiert oder miteinander multipliziert werden.
  1. Subtrahieren zweier fast gleicher Werte
           0,1235
          -0,1234
           _____
           0,0001
Dieser Wert wird normalisiert. Beachten Sie bitte, dass die ursprünglichen Zahlen jeweils vier signifikante Stellen hatten, das Ergebnis aber nur noch eine signifikante Stelle aufweist.
  1. Überlauf und Unterlauf:
    Zu diesen Fehlerbedingungen kommt es, wenn das Ergebnis zu groß oder zu klein ist, um durch den jeweiligen Datentyp dargestellt werden zu können.
  2. Quantisierungsfehler:
    Diese Fehler treten bei solchen Zahlen auf, die durch den Gleitkommastandard nicht exakt dargestellt werden können.
  3. Division durch eine sehr kleine Zahl:
    Ein solcher Vorgang kann einen Fehler des Typs "Division durch null" auslösen oder zu fehlerhaften Ergebnissen führen, wie in dem folgenden Beispiel:
          A = 112000000
          B = 100000
          C = 0,0009
          X = A - B / C
In QuickBasic für MS-DOS hat X jetzt den Wert 888887 statt der korrekten Antwort 900000.
  1. Ausgabefehler:
    Dieser Typ von Fehler tritt auf, wenn die Ausgabefunktionen die Werte ändern, mit denen sie arbeiten.
Weitere Suchbegriffe: visual basic quickbasic gleitkommamathematik gleitkommafehler vermeiden

Bitte beachten Sie: Bei diesem Artikel handelt es sich um eine Übersetzung aus dem Englischen. Es ist möglich, dass nachträgliche Änderungen bzw. Ergänzungen im englischen Originalartikel in dieser Übersetzung nicht berücksichtigt sind. Die in diesem Artikel enthaltenen Informationen basieren auf der/den englischsprachigen Produktversion(en). Die Richtigkeit dieser Informationen in Zusammenhang mit anderssprachigen Produktversionen wurde im Rahmen dieser Übersetzung nicht getestet. Microsoft stellt diese Informationen ohne Gewähr für Richtigkeit bzw. Funktionalität zur Verfügung und übernimmt auch keine Gewährleistung bezüglich der Vollständigkeit oder Richtigkeit der Übersetzung.

Eigenschaften

Artikel-ID: 42980 - Geändert am: Mittwoch, 24. August 2005 - Version: 2.2
Die Informationen in diesem Artikel beziehen sich auf:
  • Microsoft Visual Basic 2.0 Standard Edition
  • Microsoft Visual Basic 3.0 Professional Edition
  • Microsoft Visual Basic 4.0 Standard Edition
  • Microsoft Visual Basic 2.0 Professional Edition
  • Microsoft Visual Basic 3.0 Professional Edition
  • Microsoft Visual Basic 4.0 Professional Edition
  • Microsoft Visual Basic for MS-DOS
  • Microsoft Visual Basic 1.0 Standard Edition
  • Microsoft QuickBasic 4.0
  • Microsoft QuickBASIC 4.0b
  • Microsoft QuickBasic 4.5 für MS-DOS
  • Microsoft BASIC Compiler 6.0
  • Microsoft BASIC Compiler 6.0b
  • Microsoft BASIC Professional Development System 7.0
  • Microsoft Cinemania 97 Standard Edition
Keywords: 
KB42980
Microsoft stellt Ihnen die in der Knowledge Base angebotenen Artikel und Informationen als Service-Leistung zur Verfügung. Microsoft übernimmt keinerlei Gewährleistung dafür, dass die angebotenen Artikel und Informationen auch in Ihrer Einsatzumgebung die erwünschten Ergebnisse erzielen. Die Entscheidung darüber, ob und in welcher Form Sie die angebotenen Artikel und Informationen nutzen, liegt daher allein bei Ihnen. Mit Ausnahme der gesetzlichen Haftung für Vorsatz ist jede Haftung von Microsoft im Zusammenhang mit Ihrer Nutzung dieser Artikel oder Informationen ausgeschlossen.
Disclaimer zu nicht mehr gepflegten KB-Inhalten
Dieser Artikel wurde für Produkte verfasst, für die Microsoft keinen Support mehr anbietet. Der Artikel wird deshalb in der vorliegenden Form bereitgestellt und nicht mehr weiter aktualisiert.

Ihr Feedback an uns

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com