Programmiersprache Pascal

Gleitkommazahlen nach IEEE

Der Standard IEEE 754 sieht folgende rechnerinterne Darstellung für eine Gleitkommazahl vor:
  +---+-------+------------------------------+
  | S |   E   |               F              |
  +---+-------+------------------------------+
Gearbeitet wird mit einer Zahlendarstellung zur Basis 2.

Für eine Gleitkommazahl gilt:

S - Vorzeichen (sign)
1 Bit
0 : Plus, 1 : Minus

E - Exponent
8 Bit (einfach genau), 11 Bit (doppelt genau)
Der Exponent E wird nicht direkt gespeichert.
Gespeichert wird statt dessen E + 127 (einfach genau) bzw. E + 1023 (doppelt genau).

F - Mantisse (fraction)
23 Bit (einfach genau), 52 Bit (doppelt genau)
Es gilt 1.0 <= F < 2
Da die führende Ziffer stets eine 1 ist, kann darauf verzeichtet werden, sie abzuspeichern,
d.h. es wird mit einer versteckten Ziffer gearbeitet. Der Wert einer normalisierten Gleitkommazahl v ergibt sich wie folgt:
  v = (-1)S * (1.F) * 2E-127     (einfach genau)
                                 1 <= E <= 255

  v = (-1)S * (1.F) * 2E-1023    (doppelt genau)
                                 1 <= E <= 2047
Ferner gibt es denormalisierte Gleitpunktzahlen:
  v = (-1)S * (0.F) * 2-126     (einfach genau)

  v = (-1)S * (0.F) * 2-1022    (doppelt genau)
Denormalisierte Gleitpunktzahlen signalisieren Unterlauf bei Gleitpunktzahlen. Dies stellt eine sinnvolle Alternative zur Zuweisung des Wertes Null in dieser Situation dar.

Für Ausnahmesituationen sieht der IEEE-Standard spezielle Werte vor:

NaN's können in Varianten auftreten:
  NaNQ        Not a Number Quiet
  NaNS        Not a Number Signaling
Für einfache bzw. doppelte Genauigkeit gilt für die rechnerinterne Darstellung:
           S  E         E            F
              einfach   doppelt
   NaN     0  11111111  11111111111  ungleich 0
  -NaN     1  11111111  11111111111  ungleich 0
   INF     0  11111111  11111111111  0
  -INF     1  11111111  11111111111  0
Die Werte INF und -INF können durch Berechnung enstehen, z.B. durch Division durch Null oder durch Multiplikation sehr großer Zahlen.

NaN's entstehen nicht durch "normale" Berechnungen, sondern z.B. durch die Ausführung unzulässiger Operationen, wie z.B. die Division Null durch Null.
Bemerkung:
Bei der "einfachen" Division durch Null wird angenommen, daß es sich dabei um die Auswirkungen von Rundungsfehlern handelt, d.h. daß durch betragsmäßig sehr kleine Zahlen dividiert wird. Sie wird deshalb nicht als "unzulässige Operation" eingestuft.

Nicht alle Pascal-Systeme unterstützen die oben genannten Konstanten.
Das heißt, nicht alle Pascal-Systeme erzeugen z.B. bei einer Division durch Null den Wert INF bzw. -INF.
Siehe: Verhalten bei numerischen Ausnahmen

Das (wahrscheinliche) Verhalten der Systeme, welche NaN's und INF's unterstützen, läßt sich wie folgt charakterisieren:

Das folgende Programm ist - unter Umständen - geeignet, NaN's und INF's zu erzeugen:
  PROGRAM ieee1(OUTPUT);

  VAR no_num           : REAL;
      pos_inf, neg_inf : REAL;
      null             : REAL;

  BEGIN
    null    :=  0E0;
    no_num  :=  null / null;
    pos_inf :=  1E0 / null;
    neg_inf := -1E0 / null;
    Writeln(no_num, ' ', pos_inf, ' ', neg_inf);
  END.
Testergebnisse:
  XL Pascal     NaN   +INF  -INF
  Gnu Pascal    NaNQ   INF  -INF
Vergleiche

Beispiele (einfache Genauigkeit):

                             S  E         F
   0.5        16#3F000000    0  01111110  00000000000000000000000
   1.0        16#3F800000    0  01111111  00000000000000000000000
   2.0        16#40000000    0  10000000  00000000000000000000000

   MinSReal   16#00800000    0  00000001  00000000000000000000000
   MaxSReal   16#7F7FFFFF    0  11111110  11111111111111111111111

   INF        16#7F800000    0  11111111  00000000000000000000000
   NaN        16#7FFFFFFF    0  11111111  11111111111111111111111

  -INF        16#FF800000    1  11111111  00000000000000000000000
   NaN        16#FFFFFFFF    1  11111111  11111111111111111111111

  -MinSReal   16#80800000    1  00000001  00000000000000000000000
  -MaxSReal   16#FF7FFFFF    1  11111110  11111111111111111111111

   0.0        16#00000000    0  00000000  00000000000000000000000
  -0.0        16#80000000    1  00000000  00000000000000000000000

   MinDNorm   16#00000001    0  00000000  00000000000000000000001
   MaxDNorm   16#007FFFFF    0  00000000  11111111111111111111111
MinSReal
kleinste normalisierte Gleitpunktzahl mit einfacher Genauigkeit
MaxSReal
größste normalisierte Gleitpunktzahl mit einfacher Genauigkeit
MinDNorm
kleinste denormalisierte Gleitpunktzahl mit einfacher Genauigkeit
MaxDNorm
größste denormalisierte Gleitpunktzahl mit einfacher Genauigkeit

Der IEEE-Standard sieht neben der einfachen und doppelten Genauigkeit eine erweiterte Genauigkeit vor.
Die interne Darstellung einer Gleitpunktzahl mit erweiterter Genauigkeit ist durch die folgenden Werte charakterisierbar:

  S   1 Bit     Vorzeichen
  E  15 Bit     Exponent
  F  64 Bit     Mantisse
Der numerische Koprozessor 80x87, der in PC's eingesetzt wird, kann Zahlen mit erweiterter Genauigkeit verarbeiten.


Sprachsysteme setzen den IEEE-Standard nicht immer bzw. nicht immer vollständig um.
Neuere Systeme tendieren zu (weitgehender) Unterstützung, bei älteren Systeme ist mit Abweichungen zu rechnen. Vorsicht ist besonders bei Systemen angebracht, deren Wurzeln in die Zeit vor der Verabschiedung des IEEE-Standards (1985) zurückreichen.
Mitunter kann das Systemverhalten durch Compiler-Optionen beeinflußt werden.

Beispiel:
Der Datentyp REAL in Turbo Pascal bietet keine Unterstützung des IEEE-Standards. Die interne Darstellung ist "exotisch", NaN's und INF's sind nicht vorhanden.
Die Typen SINGLE, DOUBLE, EXTENDED, die an die Compiler-Option $N+ gebunden sind, sind dagegen IEEE-gerecht.



P. Böhme, 15.09.1996