for (Double i = 0.1; i <= 1.0; i++)
{
}
wie geht das? i+0.1 ging nicht
Hallo numpsy,
i += 0.1
Ist wegen der potentiellen Rundungsfehler allerdings gefährlich, es sei denn, du nimmst decimal.
herbivore
@herbivore:
das i kann man doch ruhig als double lassen, dann Rundungsfehler treten doch nicht bei der Addition bei der Laufvariablen auf?
-=MasterMax=-
Doch Rundungsfehler treten auf: bei zer Zählung von 0 bis 10: d=9.99999999999998.
Um die Rundungsfehler zu vermeiden kannst du auch:
:::
Ich habe folgenden Tests durchgeführt:
for (decimal m = 0; m < 1000000; m += 0.1m) ; //Dauer 1: 1446ms
double d2; for (int i = 10; i < 10000000; i++) d2 = i / 10d; //Dauer 2: 156ms
Edit: Meine Variante ist schneller 😄.
Hier noch der Code:
const int max1 = 1000000, max2 = max1 * 10;
DateTime a, b, c;
a = DateTime.Now;
for (decimal m = 0; m < max1; m += 0.1m) ; //Dauer 1: 479m
b = DateTime.Now;
double d2; for (int i = 10; i < max2; i++) d2 = i / 10d; //Dauer 2: 157ms
c = DateTime.Now;
MessageBox.Show("Dauer 1: " + b.Subtract(a).Milliseconds + "ms\r\n" +
"Dauer 2: " + c.Subtract(b).Milliseconds + "ms");
Es treten sehr schnell Rundungsfehler auf!
Bsp:
double sum = 0;
for (int i = 0; i < 10; i++)
{
sum = sum + 0.1;
}
// Ausgabe: 0.99999999999999989
ich würde nicht in 0.1'er Schritten aufzählen, sondern mit 1'er Schritten und würde in der Schleife mit i/10 rechnen.
Gruß
mrdjoker
Hallo MasterMax,
das i kann man doch ruhig als double lassen, dann Rundungsfehler treten doch nicht bei der Addition bei der Laufvariablen auf?
doch, es tritt sogar schon ein Rundungsfehler bei der Repräsentation von 0.1 als double auf, also bevor überhaupt damit gerechnet wurde.
herbivore
WOW, hab das gerade echt mal ausprobiert. Ich merk ich habe einfach noch nicht genug praktische Erfahrung.
Da tritt doch wirklich plötzlich so ein komischer Rundungsfehler auf. Hab bis gerade gedacht, dass sowas erst an den Grenzen von double passiert.
Gruß Timo
Hallo Omit,
Hab bis gerade gedacht, dass sowas erst an den Grenzen von double passiert.
Das solltest du weiterhin denken, denn es passiert ja an den Grenzen von double. 0.1 ist als binäre Fließkommazahl periodisch, das heißt innerhalb der Grenzen von double nicht exakt darstellbar: 0,000110011001100110011...
BTW: Dieser Fehler hat schon Leben gekostet: Runder Fehler: Das Versagen der Patriot-Abwehrrakete.
herbivore
Ja, so langsam kommt es mir wieder. Erstes Semester Rechnersysteme, als ich in ASM programmieren durfte und es um Alus ging, war da auch irgendwas mit der Gleitkommadarstellung. 😉
Ist halt immer noch ein unterschied irgendwo Wissen rumliegen zu haben oder es verknüpft und parat zu haben.
Gruß Timo
Hey Wow, habs auch gerade mal programmiert...
string s = "";
for (double d = 0; d < 10; d += 0.1)
{
s += d.ToString()+ " ";
}
s += Environment.NewLine;
s += Environment.NewLine;
for (int i = 0; i < 100; i++)
{
s += ((double)i/10).ToString() + " ";
}
MessageBox.Show(s);
Ergebnis
---------------------------
---------------------------
0 0,1 0,2 0,3 0,4 0,5 0,6 0,7 0,8 0,9 1 1,1 1,2 1,3 1,4 1,5 1,6 1,7 1,8 1,9 2 2,1 2,2 2,3 2,4 2,5 2,6 2,7 2,8 2,9 3 3,1 3,2 3,3 3,4 3,5 3,6 3,7 3,8 3,9 4 4,1 4,2 4,3 4,4 4,5 4,6 4,7 4,8 4,9 5 5,1 5,2 5,3 5,4 5,5 5,6 5,7 5,8 5,9 5,99999999999999 6,09999999999999 6,19999999999999 6,29999999999999 6,39999999999999 6,49999999999999 6,59999999999999 6,69999999999999 6,79999999999999 6,89999999999999 6,99999999999999 7,09999999999999 7,19999999999999 7,29999999999999 7,39999999999999 7,49999999999999 7,59999999999999 7,69999999999999 7,79999999999999 7,89999999999999 7,99999999999999 8,09999999999999 8,19999999999999 8,29999999999999 8,39999999999999 8,49999999999999 8,59999999999999 8,69999999999999 8,79999999999998 8,89999999999998 8,99999999999998 9,09999999999998 9,19999999999998 9,29999999999998 9,39999999999998 9,49999999999998 9,59999999999998 9,69999999999998 9,79999999999998 9,89999999999998 9,99999999999998
0 0,1 0,2 0,3 0,4 0,5 0,6 0,7 0,8 0,9 1 1,1 1,2 1,3 1,4 1,5 1,6 1,7 1,8 1,9 2 2,1 2,2 2,3 2,4 2,5 2,6 2,7 2,8 2,9 3 3,1 3,2 3,3 3,4 3,5 3,6 3,7 3,8 3,9 4 4,1 4,2 4,3 4,4 4,5 4,6 4,7 4,8 4,9 5 5,1 5,2 5,3 5,4 5,5 5,6 5,7 5,8 5,9 6 6,1 6,2 6,3 6,4 6,5 6,6 6,7 6,8 6,9 7 7,1 7,2 7,3 7,4 7,5 7,6 7,7 7,8 7,9 8 8,1 8,2 8,3 8,4 8,5 8,6 8,7 8,8 8,9 9 9,1 9,2 9,3 9,4 9,5 9,6 9,7 9,8 9,9
---------------------------
OK
---------------------------
Ich dachte wirklich die beiden wären äquivalent, da ich nur Variante 2 benutze und bei solchen Sachen noch nie Probleme mit Rundungsfehlern hatte...
Naja, wieder was gelernt =)
-=MasterMax=-
Sollte man auch beachten wenn man einen Vergleich von zwei Double-Zahlen macht, die auf unterschiedliche Weise berechnet wurden. Da kann es nämlich schnell durch die Rundungsfehler dazukommen, dass sie nicht gleich groß sind, obwohl das laut Mathematik so sein müsste. Für solche Fälle setze ich ein Delta ein, das einen gewissen Rundungsfehler erlaubt.
bool IstGleich (double dZahl1, double dZahl2)
{
bool bRetVal = false;
double dDelta = 0.000001; //erlaubte Abweichung
if ((dZahl1 >= dZahl2 - dDelta) && (dZahl1 <= dZahl2 + dDelta))
{
bRetVal = true;
}
return bRetVal;
}
"Indem Sie über dieses ernste Thema lachen disqualifizieren Sie sich selbst."
mrleeh.de
In C# wird wenigstens noch die Schleife beim überschreiten der Zählvariable abgebrochen. In VB würde eine Endlosschleife auftreten.
for d as double = 0 to 10 step 0.1
...
end for
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
[FAQ] Double und Float: Fehler beim Vergleich und Rundungsfehler
edit: seit einiger zeit vorbereitet gewesen aber bislang ncoh nciht veröffentlicht.
Das sicherste wäre doch mit Ganzzahlen zu arbeiten.
Das Runterrechnen auf double/decimal oder wen auch immer kann man dann ja in der Schleife machen.
[Edit]
Ok so ähnlich wurde das ja schon geschrieben. Geht etwas unter bei der ganzen Diskussion um Rundungsfehler.
Hallo blackman1983,
decimal arbeitet intern ja mit Ganzzahlen, bei denen per - ebenfalls ganzzahligem - Exponent das Komma verschoben wird. Insofern ist das ebenfalls sicher.
herbivore
Ah ok, wusste ich nicht.
Ich hab glaube noch nie eine Schleife mit decimal gemacht.