Sie sind auf Seite 1von 80

1

2
3
4
5
Hinweis zum selbst Testen:

Je nach verwendetem Compiler bzw. zum Einsatz kommender CPU lässt sich der
Effekt u.U. nur mit dem Datentyp float nachvollziehen. Der wahrscheinlichste
Grund dafür wird auf den nächsten Seite erklärt.

6
FPU Floating Point Unit (Gleitkommaprozessor)

Heisenberg-Effekt der Arithmetik:


Lässt man sich Zwischenergebnisse einer Rechnung, die eigentlich komplett in
den Registern ablaufen würde, ausgeben, werden diese dafür mit geringerer
Genauigkeit gespeichert, was zu Rundungsfehlern führen wird. Das Beobachten
kann also die Ergebnisse der Rechnung verändern!
(Quelle: https://www.uni-due.de/~adf040p/skripte/NumLAKSkript08.pdf)

7
8
9
http://www.radiomuseum.org/museum/d/tridelta-magnetmuseum-dortmund/.html

10
Der engl. Begriff für Gleitkommazahl ist floating point number.

11
Diese Form der Zahlendarstellung wird manchmal auch als halblogarithmische
Darstellung bezeichnet.

12
13
14
b … Basis
m … Länge (Anzahl der Stellen) der Mantisse
e … Länge (Anzahl der Stellen) des Exponenten

15
16
17
18
19
20
21
22
Im Rechner werden negative Zahlen als sog. Zweierkomplement dargestellt, was
das Rechnen mit ganzen Zahlen deutlich vereinfacht.

Beispielhafte Umwandlung der negativen Dezimalzahl −4 in die


Zweierkomplementdarstellung unter Verwendung von 8 binären Stellen:
Vorzeichen ignorieren und ins Binärsystem umrechnen: 4(10) = 00000100(2)
Invertieren: Not [00000100] = 11111011
Eins addieren: 11111011 + 00000001 = 11111100

Siehe dazu auch https://en.wikipedia.org/wiki/Two%27s_complement


(Der Artikel in der englischsprachigen Wikipedia ist mathematisch fundierter und
mit mehr und besseren Beispielen als der vergleichbare in der deutschsprachigen
Wikipedia!)

23
24
25
26
27
28
29
30
3-stellige Gleitpunktarithmetik bedeutet, dass 2590 dargestellt wird als 0.259∙104

31
32
33
34
35
36
37
38
39
40
41
42
43
44
Das 32-Bit single Gleitkommaformat entspricht dem C bzw. C++-Datentypen
float.

45
46
47
#include <cstdio>

union IEEE_754_Single
{
float Wert;
unsigned Bitmuster;
} Muster;

void printBits(const unsigned n) // n als Spezial float-Bitmuster ausgeben:


{
for (int i = 31; i >= 0; i--)
{
printf("%c", (n >> i & 1) + '0'); // i-tes Bit ausgeben
if (i == 31 or i == 23) // Trenne nach Vozeichen
printf("-"); // und Mantisse
}
printf("\n");
}

int main()
{
Muster.Wert = 3.8125;
printf("\n3.8125 in IEEE-754-Darstellung: ");
printBits(Muster.Bitmuster);
return 0;
}

Ergebnis: 3.8125 in IEEE-754-Darstellung: 0-10000000-11101000000000000000000

48
49
Abbildung:
https://tip.duke.edu/independent_learning/mathematics/algebra1_online_lesson/Lesson_12.html

50
http://en.cppreference.com/w/cpp/numeric/math/nextafter

51
https://www.inf.ethz.ch/personal/gander/Heisenberg/paper.html

52
Der kleinere Fehler bei der Berechnung auf einem PC resultiert aus der höheren
internen Bitanzahl der Gleitkommawerte in der FPU (Heisenberg-Effekt).

53
Achtung bei Exponentialdarstellungen:
2-15 ≠ 2e-15 !!
2e-15 ist gleichbedeutend mit 2∙10-15

Die verwendete Vergleichsgenauigkeit ε muss eine darstellbare Maschinenzahl


sein, z.B. eine Zweierpotenz. Sonst schleichen sich bei dem Vergleichsoperator <
erneute Fehler ein.
Die Vergleichsgenauigkeit ε darf auch nicht kleiner als die Maschinengenauigkeit
eps sein (Seite 37), da die Operationen sonst sinnlos ist.

54
55
56
Ein Beispiel auf einem PC:
#include <iostream>
#include <cmath>

using namespace std;

int main()
{
cout.precision(18);

for (float i = 1.0f; i<= 10.0f; i++)


{
cout << scientific << sin(1.0f + pow(10.0f, -i)) –
sin(1.0f) << endl;
}
return 0;
}
Ergebnis:
4.973641407364119700e-002
5.360882743427888700e-003
5.399346949024267800e-004
5.406299301401396500e-005
5.438323878466822400e-006
5.432775778873091800e-007
9.241457638877424700e-008
2.800552834260209100e-008
2.800552834260209100e-008
2.800552834260209100e-008

Die Werte im Ergebnis unterscheiden sich etwas zu o.a. Beispiel durch die Verwendung
der 64-FPU und der internen Gleitkommadarstellung

57
Δ1f (1, h) wird, wenn Sie das Beispiel der vorigen Seite auf Ihrem Rechner
ausprogrammieren, irgendwann Null werden. Warum ist das so?
Hinweis:
Denken Sie an den maximal auftretenden Fehler bei Rundung.

Sie müssen allerdings auch float überall durch double ersetzen und i etwas
weiter laufen lassen, damit der Effekt auftritt (wegen der internen FPU-
Genauigkeit kann dieses Phänomen mit float nicht erreicht werden).

58
59
60
61
Herleitung des absoluten Fehlers der Multiplikation
𝑥 − 𝑥෤ 𝑦 − 𝑦෤ = 𝑥𝑦 − 𝑥𝑦෤ − 𝑥𝑦
෤ + 𝑥෤ 𝑦෤ |− 𝑥 − 𝑥෤ 𝑦 − 𝑦෤
0 = 𝑥𝑦 − 𝑥𝑦෤ − 𝑥𝑦
෤ + 𝑥෤ 𝑦෤ − 𝑥 − 𝑥෤ 𝑦 − 𝑦෤ |−𝑥෤ 𝑦෤
−𝑥෤ 𝑦෤ = 𝑥𝑦 − 𝑥𝑦෤ − 𝑥𝑦
෤ − 𝑥 − 𝑥෤ 𝑦 − 𝑦෤ |+𝑥𝑦
𝑥𝑦 − 𝑥෤ 𝑦෤ = 𝑥𝑦 − 𝑥𝑦෤ − 𝑥𝑦
෤ + 𝑥𝑦 − 𝑥 − 𝑥෤ 𝑦 − 𝑦෤ −𝑥𝑦
෤ + 𝑥𝑦 → 𝑦(𝑥 − 𝑥)

𝑥𝑦 − 𝑥෤ 𝑦෤ = 𝑥 𝑦 − 𝑦෤ + 𝑦 𝑥 − 𝑥෤ − (𝑥 − 𝑥)(𝑦
෤ − 𝑦)

62
63
64
Man beachte den Unterschied zwischen einer Abschätzung und einer Schätzung.
Eine Abschätzung liefert eine gesicherte Aussage. Eine Schätzung dagegen liefert
eine ungefähre Zahl, die den echten Wert gut wiedergeben kann oder auch nicht.

65
66
67
68
69
70
71
https://xkcd.com/1856/

72
73
74
75
76
77
+∞ wird bei Ausgabe in C dargestellt als inf, in C++ als 1.#INF
−∞ wird bei Ausgabe in C dargestellt als -inf, in C++ als -1.#INF

78
79
80