Home » Tutorials » Sonstiges » Eins null eins null eins null – Wie Delphi intern tickt

Eins null eins null eins null – Wie Delphi intern tickt

Runden

Häufiger wird die Frage gestellt, warum Delphi manchmal „komisch“ rundet. Ein solches Beispiel wäre folgendes:

var e: Extended;
begin
  e := 100.5;
  writeln(round(e));
  e := 101.5;
  writeln(round(e));
  readln;
end .

Normalerweise würde man nun die Ausgabe 101 und 102 erwarten, da bei einer Nachkommastelle größergleich fünf immer aufgerundet wird. Tatsächlich erhalten wir aber die Ausgabe
100
102
Warum? Delphi besitzt unterschiedliche Rundungsmodi. Unterschieden werden vier verschiedene Modi, die über die Routine setRoundMode der Math-Unit gesetzt werden können:

  • rmNearest
  • rmDown
  • rmUp
  • rmTruncate

rmNearest rundet zum nächsten geraden Wert. Das wird gemacht, damit sich Rundungsfehler bei längeren Rechnungen in der Waage halten und gegenseitig ausgleichen. Folgende Tabelle zeigt an einigen Beispielen das rmNearest-Runden.

Zahl: 0.5 1.5 2.5 -0.5 -1.5 -2.5
Gerundete Zahl: 2 2 -2 -2

rmDown rundet immer in Richtung minus unendlich. Das bedeutet, dass selbst 2.9 gerundet als 2 erscheint. Hingegen wird -2.9 zu -3. Und sogar -2.1 würde zu -3 gerundet werden. Deutlich wird das auch in folgender Tabelle.

Zahl: 0.5 1.5 2.5 -0.5 -1.5 -2.5
Gerundete Zahl: 1 2 -1 -2 -3

Das Gegenteil davon ist rmUp. Hier wird immer in Richtung plus unendlich gerundet. Die Tabelle kehrt sich also gewissermaßen genau um.

Zahl: 0.5 1.5 2.5 -0.5 -1.5 -2.5
Gerundete Zahl: 1 2 3 -1 -2

Der letzte im Bunde ist rmTruncate. Er ist eine Mischung aus rmDown und rmUp, denn bei diesem Modus wird der Wert einfach abgeschnitten. Positive Werte werden dann in Richtung minus unendlich gerundet, negative Werte aber in Richtung plus unendlich. Oder anders gesagt: Es wird immer in Richtung der Null gerundet. Somit würden 1.1 und 1.9 beide auf 1 gerundet werden, ebenso wie -1.1 und -1.9 in Richtung der Null auf -1 gebracht werden würden. Die Tabelle dazu:

Zahl: 0.5 1.5 2.5 -0.5 -1.5 -2.5
Gerundete Zahl: 1 2 -1 -2

Nun können wir auch unsere anfängliche Frage beantworten, warum sich Delphi so seltsam verhält. Delphi rechnet standardmäßig mit rmNearest. Daher wurden beide Zahlen, obgleich sie dieselbe Nachkommastelle hatten, unterschiedlich gerundet. Zu erwähnen blieb noch, dass die truncate-Routine in der Regel die schnellste von allen ist, dafür allerdings auch die größten Rundungsfehler mit sich bringt. Berechnet man mehrere Zahlen hintereinander mit dieser Methode, so können schnell große Fehler entstehen.