Wieso wird folgender Quellcode endlos ausgeführt ?
double x = 2.0; while (x != 3.0) // Solange x nicht 3.0 ist, tue { Console.WriteLine(x); x = x + 0.1; }
Gleitkommazahlen sind nur Näherungen
Reelle Zahlen sind Zahlen, die Nachkommastellen haben. Manche dieser Zahlen sind vollkommen unproblematisch. Zum Beispiel 3,5. Diese Zahl entsteht beispielsweise, wenn man 7 durch 2 teilt.
Schwieriger sind jedoch Zahlen die kein Ende haben, also unendlich viele Nachkommstellen. Hierzu zählt zum Beispiel das Ergebnis aus 10 geteilt durch 3. Es ist 3,33333…
Ein Computer kann jedoch nicht problemlos eine unendliche Zahl anzeigen, bzw. berechnen. Das würde ja bedeuten, dass er unendlich lang diese Zahl ausdrucken müsste oder er unendlich viel Speicher besitzen müsste.
Aus diesem Grund beschränkt man sich auf eine bestimmte Anzahl an Nachkommastellen. Nehmen wir beispielsweise 10 Euro. Wenn man die durch drei teilen würde, würde jeder 3,33 Euro bekommen. Es bleibt dann jedoch ein Cent übrig. Wir geben uns also auch im realen Leben mit einer guten Näherung zufrieden.
Quelle: http://www.ulthryvasse.de/gleitkommazahlen.html#a1089
Umrechnung
Die Zahl 0.1 wird vom Computer wie folgt ins Binärsystem umgerechnet:
0.1 = 1.00 * 10^{-1} = \frac{1}{10} = 00111101110011001100110011001101 _{2}
Hier wird der Unterschied klarer wieso 0.1 als Interger, float und dobule nicht exakt den selben Wert entsprechen.
Zahl | Wert |
0.1 | 0.1 (Natürlich) |
float(.1) | 0.100000001490116119384765625 |
double(.1) | 0.10000000000000000555111512312578270211815834045 41015625 |
Fazit
Computer können keine reellen Zahlen abspeichern. Abgespeicherte Zahlenmenge < \mathbb{R}.
Gleitkommazahlen (float, double, …) dürfen NIE auf Gleichheit oder Ungleichheit verglichen werden.