2009-04-06 5 views

Antwort

14

ist nicht exakt 1,0 sein könnte nehme ich an Sie die Frage auf Jon Skeet Denkaufgaben Seite gefunden? Die Antworten sind here auf der gleichen Website aufgeführt und erläutert.

Für eine Frage der Referenz ist hier die Antwort von dieser Seite kopiert.


3) Dumme Arithmetik

Computer gemeint sind bei Arithmetik, gut zu sein, nicht wahr? Warum wird "False" gedruckt?

double d1 = 1.000001; double d2 = 
0.000001; Console.WriteLine((d1-d2)==1.0); 

Antwort: Alle Werte sind hier als binäre Gleitkommazahl gespeichert. Während 1,0 genau gespeichert werden kann, wird 1,000001 tatsächlich als 1,0000009999999999177333620536956004798412322998046875 gespeichert, und 0,000001 wird tatsächlich als 0,000000999999999999995474811182588625868561393853648808787366455078125 gespeichert. Der Unterschied zwischen ihnen ist nicht genau 1,0, und tatsächlich kann der Unterschied auch nicht genau gespeichert werden.

+0

verwendet wird, ist es anice Beispiel – IloveIniesta

2

Es ist, weil Computer Mathematik in der Basis 2, und damit viele Dezimal-Gleitkommazahlen tun können nicht genau mit einer begrenzten Anzahl von Ziffern dargestellt werden.

1

dieser Punkt Präzision Probleme zurückzuführen sein kann, um schwimmend, wie es, dass Ihr Ergebnis aber vielleicht so etwas wie 1,000000000001

1

Dies passiert, weil Fließkommatypen Zahlen mit einer Basis zwei und nicht eine Basis zehn Darstellung speichern. Dies hat zur Folge, dass double Werte wie 0.1 nicht genau speichern kann. Zum Beispiel wird 0,1 durch den Einzelwert 0,100000001490116119384765625 dargestellt.

Sie müssen Decimal verwenden, um den Fehler loszuwerden.

1

Dies ist auf die Art und Weise, dass in der CPU-Nummern arbeiten Punkt schweben, es ist nicht C# spezifisch. Siehe this Wikipedia-Eintrag und das Papier here für weitere Informationen.

Die kurze Antwort ist, dass Fließkommazahlen nicht als exakte Darstellung gespeichert werden, so dass ein Vergleich mit "==" nicht so funktioniert, wie Sie es verwenden möchten.

3

Aus der MSDN-Eintrag für Double.Equals:

Präzision im Vergleich

Die Equals-Methode mit Vorsicht verwendet werden sollten, weil zwei scheinbar äquivalente Werte aufgrund der unterschiedlichen ungleich sein kann Genauigkeit der beiden Werte. Im folgenden Beispiel wird gemeldet, dass der Double-Wert .3333 und der Double, der durch Division von 1 durch 3 zurückgegeben wird, ungleich sind.

...

Anstatt Gleichheit zu vergleichen, eine empfohlene Technik beinhaltet eine akzeptable Marge von Differenz zwischen zwei Werten (wie .01% der einer der Werte) definieren. Wenn der absolute Wert der Differenz zwischen den beiden Werten kleiner als oder gleich die Spanne ist die Differenz wahrscheinlich in Präzision und daher aufgrund von Unterschieden sein, die Werte sind wahrscheinlich gleich ist. Das folgende Beispiel verwendet diese Technik, um .33333 und 1/3, die zwei Doppelwerte , die das vorherige Codebeispiel ungleich zu sein.

Wenn Sie eine Menge von „Gleichheit“ Vergleichen tun müssen, könnte es eine gute Idee sein, eine kleine Hilfsfunktion oder Extension-Methode in .NET 3.5 zu schreiben, zum Vergleichen:

public static bool AlmostEquals(this double double1, double double2, double precision) 
{ 
    return (Math.Abs(double1 - double2) <= precision); 
} 

Dies könnte die folgende Art und Weise verwendet:

double d1 = 1.000001; 

double d2 = 0.000001; 

bool equals = (d1 - d2).AlmostEquals(1.0, 0.0000001); 

sehen Sie diese ganz ähnliche Frage: C#.NET: Is it safe to check floating point values for equality to 0?

+1

, warum die niedergeschlagene und kein Kommentar? +1, um die -1 rückgängig zu machen. Die Antwort ist möglicherweise nicht genau das, was der Benutzer fragt, aber es bietet eine Möglichkeit, nach solchen Berechnungen zu suchen. –

2

Wenn Sie ein solches tun in Ihrer Anwendung rithmetic sollte der decimal Typ

decimal d1 = 1.000001M; 

decimal d2 = 0.000001M; 

Console.WriteLine((d1 - d2) == 1.0M); // evaluates as true 
+1

Vorsicht! dezimal hat auch eine begrenzte Genauigkeit. Beispiel: dezimal d1 = 1.0M/3.0M; Dezimal d2 = 3,0 M; (d1 * d2) == 1,0 M; // <- das gibt falsch! –

Verwandte Themen