Programmiersprache Pascal

Verhalten bei numerischen Ausnahmen

Untersucht werden soll das Verhalten verschiedener Pascal-Systeme bei numerischen Ausnahmen wie

Division durch Null - Gleitpunkt

Das Standardverhalten der verschiedenen Pascal-Systeme ist unterschiedlich:

Testprogramm
  PROGRAM num_div0(OUTPUT);
  VAR x1, x2, y : REAL;
  BEGIN
    x1 := 1.0;
    x2 := 0.0;
    y := x1/x2;
    Writeln(x1, ' ', x2, ' ', y);
  END.
Turbo Pascal 7.0
  Runtime error 200 at 0000:004F.
Pascal++
  *** ERROR LINE 6 4018 : Real division by zero
Gnu Pascal
   1.0000000e+00  0.0000000e+00  INF
XL Pascal
   1.000000000000E+000  0.000000000000E+000                 +INF

Division durch Null - Festpunkt

Testprogramm

  PROGRAM fixerr(OUTPUT);

  VAR i, j, k : INTEGER;

  BEGIN
    i := 1;  j := 0;
    k := i DIV j;
    Writeln(k);
  END.
Turbo Pascal 7.0
  Runtime error 200 at 0000:001E.
Gnu Pascal
  -2147483648
Pascal++
  *** ERROR LINE 7 4015 : Integer division by zero with DIV
XL Pascal
  Trace/BPT trap(coredump)

Exponentenüberlauf - Gleitpunkt

Das Standardverhalten der verschiedenen Pascal-Systeme ist unterschiedlich:

Testprogramm
  PROGRAM num_ovf(OUTPUT);
  VAR x, y : REAL;
  BEGIN
    x := 1.0e200;
    y := x*x;
    Writeln(x, ' ', y);
  END.
Pascal++
   1.0E+0200 ˜ Inf
Gnu Pascal
   1.0000000e+200  INF
XL Pascal
   1.000000000000E+200                 +INF
Turbo Pascal
  x := 1.0e200;  führt zu Übersetzungsfehler 
                 wegen Wertebereichsüberschreitung
  x := 1.0e20;   führt zu 
                 Runtime error 205 at 0000:0042

Überlauf - Festpunkt

Überschreitungen des Wertebereichs werden bei den meisten Systemen im Standardfall nicht signalisiert.
Dieses Verhalten ist gegebenenfalls mittels Compileroption modifizierbar.

Testprogramm

  PROGRAM fixerr(OUTPUT);

  VAR i, k : INTEGER;

  BEGIN
    i := MaxInt;
    k := i + 1;
    Writeln(k);
  END.
Turbo Pascal 7.0
  -32768               { MaxInt = 32767 }
Pascal++, Gnu Pascal, XL Pascal, Delphi32
  -2147483648          { MaxInt = 2147483647 }

Exponentenunterlauf

Testprogramm

  PROGRAM num_udf(OUTPUT);
  VAR x, y : REAL;
  BEGIN
    x := 1.0e-200;
    y := x*x;
    Writeln(x, ' ', y);
  END.
Das Standardverhalten besteht in der stillschweigenden Korrektur des Wertes der Ergebnisvariable auf den Wert Null.


Nutzung mathematischer Standardfunktionen außerhalb des Definitionsbereichs

Das Standardverhalten der verschiedenen Pascal-Systeme ist unterschiedlich:

Testprogramm 1
  PROGRAM num_math(OUTPUT);
  VAR x, y : REAL;
  BEGIN
    x := -1.0;
    y := Ln(x);
    Writeln(x, ' ', y);
  END.
Gnu Pascal
  ?GPC runtime error: Argument of Ln is <= 0 (#33)
Pascal++
  *** ERROR LINE 5 4019 : The argument to predefined function LN must be greater than zero
XL Pascal
  -1.000000000000E+000                  NaN
Turbo Pascal
  Runtime error 207 at 0000:0031

Testprogramm 2

  PROGRAM sqrterr(OUTPUT);
  
  VAR x, y : REAL;
  
  BEGIN
    x := -1;
    y := Sqrt(x);
    Writeln(x, ' ', y);
  END.
Turbo Pascal 7.0
  Runtime error 207 at 0000:0031
Pascal++
  *** ERROR LINE 7 4020 : SQRT of negative value
Gnu Pascal
  ?GPC runtime error: Argument of Sqrt is < 0 (#34)
XL Pascal
  -1.000000000000E+000                  NaN

Unzulässige Literale beim Lesen von einer Zeichenkette

Extended Pascal, XL Pascal

Das Standardverhalten der verschiedenen Pascal-Systeme ist unterschiedlich:

Testprogramm
  PROGRAM num_read(OUTPUT);
  VAR x1, x2 : REAL;
      s1, s2 : STRING(10);
  BEGIN
    s1 := '1.0x20';
    ReadStr(s1, x1);
    Writeln(s1, ' ', x1);
    s2 := 'Unfug';
    ReadStr(s2, x2);
    Writeln(s2, ' ', x2);
  END.  
Gnu Pascal
  1.0x20  1.0000000e+00
  ?GPC runtime error: Sign or digit expected (#605)
Pascal++
  *** ERROR LINE 6 4033 : Unexpected character met during reading of a real number
XL Pascal
  1.0x20  1.000000000000E+000
  1527-026 Error during real read for READSTR.
           Processing will continue.
  Unfug  0.000000000000E+000
Turbo Pascal

Testprogramm
Bemerkung: Das obige Testprogramm ist für Turbo Pascal nicht einsetzbar.

  PROGRAM num_readt;
  VAR x1, x2 : REAL;
      s1, s2 : STRING[20];
      ie1, ie2 : INTEGER;             { Fehlerindikator }
  BEGIN
    s1 := '1.0x20';
    Val(s1, x1, ie1);
    Writeln(s1, ' ', x1, ' ', ie1);
    s2 := 'Unfug';
    Val(s2, x2, ie2);
    Writeln(s2, ' ', x2, ' ', ie2);
  END.
Ergebnis
  1.0x20  0.0000000000E+00 4
  Unfug  0.0000000000E+00 1
Im Fehlerfall wird ein Standardwert (Null) zugewiesen. Durch Auswertung eines Indikators kann auf einen Fehler geschlossen werden (Indikator ungleich Null: Fehler).


Wertebereichsverletzungen bei Aufzählungsdatentypen

Testprogramm

  PROGRAM enumerr(OUTPUT);
  
  TYPE farbe = (rot, gruen, blau);
  
  VAR f1, f2 : farbe;
  
  BEGIN
    f1 := rot;
    f2 := Pred(f1);
    Writeln(Ord(f1), ' ', Ord(f2));
  END.
Turbo Pascal 7.0
  0 -1
Delphi32
  0 255                                 { Standard }
  Runtime error 201 at 00000E38         { Compiler-Option $R+ }
Pascal ++
  *** ERROR LINE 9 4043 :  Value could not be decremented with 1 in pred function
Gnu Pascal
           0         -1
XL Pascal
             0          255

Die obigen Beispiele zeigen eindeutig, daß der Programmierer bei der Umsetzung mathematischer Algorithmen sehr sorgfältig über das mögliche Auftreten von Ausnahmesituationen und die Behandlung dieser Situationen nachdenken muß.
Gleiches Programmverhalten bei Nutzung unterschiedlicher Systeme läßt sich nur erreichen, wenn der Programmierer verhindert, daß das Programm in eine Ausnahmesituation gerät.

Sprachmittel zur Behandlung von Ausnahmesituationen sind in einigen neueren Pascal-Systemen verfügbar, gewährleisten zur Zeit aber keinerlei Portabilität.

Siehe: Abfangen von numerischen Ausnahmen in Delphi

Bemerkung:
Die obigen Beispiele demonstrieren nebenbei das unterschiedliche Ausgabeverhalten der verschiedenen Pascal-Systeme bei der Verwendung von Writeln ohne Format-Deskriptoren.



P. Böhme, 27.08.1996