Programmierkurs
für Naturwissenschaftler/innen

Worauf ist bei numerischen Berechnungen zu achten: Einführung in Fehler

Abschließend möchte ich noch auf einige Dinge hinweisen, die beim Schreiben von numerischen Programmen zu beachten sind.

Einer der wichtigsten Punkte, die bei numerischen Berechnungen zu beachten ist, ist das Problem der Fehler. Numerische Berechnungen sind ein Kampf gegen Fehler. (Darüber hinaus kämpfen wir auch mit der Rechenzeit und der Speicherkapazität. Es gibt viele Feinde.)

Hier werde ich einige sehr einfache Beispiele vorstellen.

Vorsicht vor Dezimalbruch

Auf den ersten Blick könnte die Zahl 0.1 wie eine saubere Zahl aussehen. Das liegt aber nur an der besonderen Situation des Dezimalsystems, was anderswo nicht unbedingt der Fall ist. In der Tat ist die binäre Darstellung von 0.1

0.000110011…

was ein unendlicher binärer Bruch ist.

Da Computer intern Binärzahlen verarbeiten und nicht mit unendlich vielen Ziffern umgehen können, müssen sie irgendwo auf- oder abrunden. Dies führt zu einem Fehler (Rundungsfehler).

Aus diesem Grund ergibt die zehnfache Addition von 0.1 nicht immer 1.

Überlegen Sie, was passiert (oder passieren sollte), wenn Sie das folgende Programm ausführen. Geben Sie dann dieses Programm in das Textfeld ein und versuchen Sie, es auszuführen.

let sum = 0;

for (let i = 0; i < 10; i++) {
  sum += 0.1;
  console.log(sum)
}

Ergebnis

Sie werden wahrscheinlich das folgende Ergebnis erhalten.

0.1
0.2
0.30000000000000004
0.4
0.5
0.6
0.7
0.7999999999999999
0.8999999999999999
0.9999999999999999

Daher führt der Vergleich von Dezimalzahlen mit == nicht immer zu dem erwarteten Ergebnis.

Überlegen Sie, was passiert (oder passieren sollte), wenn Sie das folgende Programm ausführen. Geben Sie dann dieses Programm in das Textfeld ein und versuchen Sie, es auszuführen.

let sum = 0;

for (let i = 0; i < 20; i++) {
  sum += 0.1;
  if (sum == 1) {
    console.log("Now sum is 1");
  }
}
console.log("sum is ", sum);

Ergebnis

Vergleichen Sie Dezimalzahlen nicht mit ==.

Vorsicht bei der Subtraktion

Die Subtraktion von sehr nahen Zahlen (ein sehr vager Begriff, auf den wir hier aber nicht näher eingehen wollen) führt manchmal nicht zum erwarteten Ergebnis.

Nehmen wir zum Beispiel $1.00000001 - 1$.

  1. Berechnen Sie $(1.00000001 - 1)$ mit Papier und Bleistift.

  2. Führen Sie diese Berechnung mit dem folgenden Programm durch.

let n1     = 1.00000001;
let n2     = 1;
let answer = 0.00000001;

console.log(n1 - n2);
console.log("The answer should be:", answer);

Ergebnis

Wie dieses Beispiel zeigt, ist es nicht so, dass die Zahl 0.00000001 (= 1e-08) nicht dargestellt werden kann (answer wird korrekt dargestellt), sondern dass der Fehler durch die Subtraktion verursacht wird.

Aufgrund dieses Problems wird die numerische Differenzierung im Allgemeinen als eine der schwierigeren Berechnungen für Computer angesehen.

Nun möchten Sie vielleicht fragen: Wie genau kann ich dieses Problem vermeiden? Leider kommt es darauf an. Man kann beispielsweise die Reihenfolge der Berechnungen ändern, oder man kann den Algorithmus ändern, aber welche Methode am besten ist, hängt vom Problem ab.

Vorsicht bei der Addition

Die Addition von sehr großen und sehr kleinen Zahlen funktioniert eventuell nicht.

Das folgende Programm addiert 100 Mal 1e-10 ($= 0.000 000 000 1$) zu 1e7 ($= 10,000,000$). Führen Sie das aus.

let n1 = 1e7;
let n2 = 1e-10;

let n = n1;
for (let i = 0; i < 100; i++) {
  n += n2;
}
console.log(n);

let answer = n1 + n2 * 100;
console.log("The answer should be:", answer);

Ergebnis

Diese ist leichter zu verstehen, wenn man sie in Dezimalzahlen betrachtet. Bei drei signifikanten Stellen ergibt die Addition von 0.01 zu 10.0 $$ 10.0 + 0.01 = 10.0\cancel{1} = 10.0 \quad . $$ Es ist also egal, wie oft 0.01 zu 10.0 addiert wird, es ist immer noch 10.0.

Dieses Problem kann auftreten, wenn die Anzahl der Teilungen bei der numerischen Integration extrem groß ist.