Frage

Ich weiß, dass Sie normalerweise nicht auf Gleichheit zwischen Doppel- oder dezimal Typ Werte verlassen können, aber ich frage mich, ob 0 ein Sonderfall ist.

Während ich Unschärfen zwischen ,00000000000001 und ,00000000000002 verstehen, 0 selbst scheint ziemlich schwer zu verderben, da es einfach nichts ist. Wenn Sie ungenau nichts sind, ist es nicht nichts mehr.

Aber ich weiß nicht viel über dieses Thema, es ist also nicht für mich zu sagen.

double x = 0.0;
return (x == 0.0) ? true : false;

Wird die immer true zurück?

War es hilfreich?

Lösung

Es ist sicher erwarten, dass der Vergleich true zurück, wenn und nur wenn die doppelte Variable einen Wert von genau 0.0 hat (die in Ihrem ursprünglichen Code-Schnipsel ist, natürlich, der Fall ist). Dies steht im Einklang mit der Semantik des == Operators. a == b bedeutet "a ist gleich b".

Es ist nicht sicher (weil es nicht korrekt ) erwarten, dass das Ergebnis einer Berechnung Null in doppelt so hoch sein wird (oder allgemeiner, Gleitkomma) arithmetics immer dann, wenn das Ergebnis der Berechnung in der gleichen reiner Mathematik ist Null. Dies liegt daran, wenn Berechnungen in den Boden kommen, Punktgenauigkeit Fehler floating erscheinen -. Ein Konzept, das in Realzahl-Arithmetik in Mathematik existiert nicht

Andere Tipps

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 für den Vergleich zu schreiben:

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

Die folgende Art und Weise verwendet werden:

double d1 = 10.0 * .1;
bool equals = d1.AlmostEquals(0.0, 0.0000001);

Für Ihre einfache Probe, dass Test ist in Ordnung. Aber was ist das:

bool b = ( 10.0 * .1 - 1.0 == 0.0 );

Beachten Sie, dass eine sich wiederholende 0,1 dezimal in binär ist und kann nicht exakt dargestellt werden. Dann vergleichen Sie das mit diesem Code:

double d1 = 10.0 * .1; // make sure the compiler hasn't optimized the .1 issue away
bool b = ( d1 - 1.0 == 0.0 );

Ich werde Sie lassen einen Test ausführen, um die tatsächlichen Ergebnisse zu sehen: Sie sind eher, um es auf diese Weise erinnern

.

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

  

Präzision im Vergleich

     

Die Equals-Methode verwendet werden soll, mit   Vorsicht, weil zwei scheinbar   äquivalente Werte können aufgrund ungleich sein   auf die unterschiedliche Genauigkeit der beiden   Werte. Im folgenden Beispiel Berichte   dass der Double-Wert 0,3333 und die   Zu, indem 1 durch 3 dividiert sind   ungleich.

     

...

     

Anstatt auf Gleichheit zu vergleichen,   eine empfohlene Technik beinhaltet   Definieren eines akzeptablen Spanne   Differenz zwischen zwei Werten (wie beispielsweise   .01% einer der Werte). wenn die   absoluter Wert der Differenz   zwischen den beiden Werten kleiner als oder   gleich diesen Rand, die Differenz   ist wahrscheinlich auf Unterschiede sein in   Präzision und damit die Werte   sind wahrscheinlich gleich sein. Folgende   Beispiel verwendet diese Technik vergleichen   0,33333 und 1/3, die beiden Doppelwerte   dass das vorherige Codebeispiel gefunden   zu ungleich.

Auch finden Sie unter Double.Epsilon .

Das Problem kommt, wenn Sie verschiedene Arten von Gleitkommawert Implementierung verglichen werden z.B. Vergleich Schwimmer mit Doppel. Aber mit dem gleichen Typ, es sollte kein Problem sein.

float f = 0.1F;
bool b1 = (f == 0.1); //returns false
bool b2 = (f == 0.1F); //returns true

Das Problem ist, Programmierer vergisst manchmal, dass implizite Typumwandlung (Doppel zu schweben) für den Vergleich geschieht, und die es Ergebnisse in einen Fehler.

Wenn die Nummer direkt mit dem Schwimmer zugeordnet wurde oder Doppel dann ist es sicher gegen Null oder eine ganze Zahl zu testen, die in 53 Bits für einen Doppel- oder 24 Bits für einen Schwimmer dargestellt werden können.

Oder anders platzieren können Sie immer zuweisen und Integer-Wert zu einem Doppelbett und dann die doppelten wieder auf die gleiche ganze Zahl vergleichen, und es wird gleich garantiert werden.

Sie können auch durch die Zuweisung einer ganzen Zahl beginnen und haben eine einfache Vergleiche durch Festhalten an Addieren, Subtrahieren oder Multiplikation mit ganzen Zahlen arbeiten fortsetzen (vorausgesetzt, das Ergebnis ist weniger als 24 Bits für einen Schwimmer abd 53 Bits für ein Doppelzimmer) . So können Sie floats und double als ganze Zahlen unter bestimmten kontrollierten Bedingungen behandeln.

Nein, es ist nicht in Ordnung. Sogenannter denormalisierter Wert (subnormal), wenn auf 0,0 gleich verglichen, würde vergleichen als falsch (nicht Null), aber wenn in einer Gleichung verwendet würde normalisiert werden (werden 0,0). Somit wird unter Verwendung dieses als Mechanismus eine Division durch Null zu vermeiden ist nicht sicher. Stattdessen fügen 1.0 und 1.0 vergleichen. Dadurch wird sichergestellt, dass alle subnormals als Null behandelt werden.

Versuchen Sie dies, und Sie werden feststellen, dass == für Doppel / Schwimmer nicht zuverlässig ist.
double d = 0.1 + 0.2; bool b = d == 0.3;

Hier ist die Antwort von Quoren.

Tatsächlich, ich denke, es ist besser, die folgenden Codes verwenden, um einen doppelten Wert gegenüber auf 0,0 vergleichen:

double x = 0.0;
return (Math.Abs(x) < double.Epsilon) ? true : false;

Das Gleiche gilt für float:

float x = 0.0f;
return (Math.Abs(x) < float.Epsilon) ? true : false;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top