Entschuldigung, das mag eine einfache, dumme Frage sein, aber ich muss es wissen, um sicher zu sein.
Ich habe diesen if
Ausdruck,
void Foo()
{
System.Double something = GetSomething();
if (something == 0) //Comparison of floating point numbers with equality
// operator. Possible loss of precision while rounding value
{}
}
Ist dieser Ausdruck gleich mit
void Foo()
{
System.Double something = GetSomething();
if (something < 1)
{}
}
? Denn dann könnte ich ein Problem haben, das if
mit zB einem Wert von 0,9 einzugeben.
// Comparison of floating point numbers with equality // operator.
Mussten Sie das wirklich angeben? :)Antworten:
Nun, wie nahe muss der Wert bei 0 liegen? Wenn Sie viele Gleitkommaoperationen durchlaufen, die bei "unendlicher Genauigkeit" zu 0 führen können, erhalten Sie möglicherweise ein Ergebnis "sehr nahe" an 0.
In der Regel möchten Sie in dieser Situation eine Art Epsilon bereitstellen und überprüfen, ob das Ergebnis genau innerhalb dieses Epsilons liegt:
Das Epsilon, das Sie verwenden sollten, ist anwendungsspezifisch - es hängt davon ab, was Sie tun.
Wenn das Ergebnis genau Null sein sollte, ist eine einfache Gleichheitsprüfung natürlich in Ordnung.
quelle
== 0
. Sie haben dort ein Literal - das ist ziemlich konstant :)Wenn
something
das Ergebnis einer anderen Operation als der zugewiesen wurde, verwendensomething = 0
Sie besser:Bearbeiten : Dieser Code ist falsch. Epsilon ist die kleinste Zahl, aber nicht ganz Null. Wenn Sie eine Zahl mit einer anderen Zahl vergleichen möchten, müssen Sie sich überlegen, welche Toleranz akzeptabel ist. Nehmen wir an, dass alles, was über .00001 hinausgeht, Sie nicht interessiert. Das ist die Nummer, die Sie verwenden würden. Der Wert hängt von der Domain ab. Es ist jedoch meistens nie Double.Epsilon.
quelle
Math.Abs(0.1f - 0.1d) < double.Epsilon
istfalse
double d = Math.Sqrt(10100)*2; double a = Math.Sqrt(40400); if(Math.Abs(a - d) < double.Epsilon) { Console.WriteLine("true"); }
Ihr
something
ist eindouble
, und Sie haben das in der Zeile richtig identifiziertWir haben eine
double
auf der linken Seite (lhs) und eineint
auf der rechten Seite (rhs).Aber jetzt scheint es so, als ob Sie denken, dass die lhs in eine konvertiert werden
int
, und dann==
vergleicht das Vorzeichen zwei ganze Zahlen. Das ist nicht , was passiert. Die Konvertierung vondouble
nachint
ist explizit und kann nicht "automatisch" erfolgen.Stattdessen passiert das Gegenteil. Das rhs wird in konvertiert
double
, und dann wird das==
Vorzeichen zu einem Gleichheitstest zwischen zwei Doppelwerten. Diese Konvertierung ist implizit (automatisch).Es wird (von einigen) als besser angesehen, zu schreiben
oder
denn dann ist es sofort, dass Sie zwei Doppel vergleichen. Dies ist jedoch nur eine Frage des Stils und der Lesbarkeit, da der Compiler auf jeden Fall das Gleiche tut.
In einigen Fällen ist es auch relevant, eine "Toleranz" wie in Jon Skeets Antwort einzuführen, aber diese Toleranz wäre auch eine
double
. Es könnte natürlich sein,1.0
wenn Sie wollten, aber es muss nicht [die am wenigsten streng positive] Ganzzahl sein.quelle
Wenn Sie die Warnung einfach unterdrücken möchten, gehen Sie folgendermaßen vor:
Dies ist natürlich nur dann eine gültige Lösung, wenn Sie wissen, dass Drift kein Problem darstellt. Ich mache das oft, um zu überprüfen, ob ich durch Null teilen werde.
quelle
Ich glaube nicht, dass es gleich ist, ehrlich. Betrachten Sie Ihr eigenes Beispiel: etwas = 0,9 oder 0,0004. Im ersten Fall ist es FALSE, im zweiten Fall ist es TRUE. Der Umgang mit diesen Typen definiere ich normalerweise für mich Präzisionsprozentsatz und vergleiche innerhalb dieser Präzision. Kommt auf deine Bedürfnisse an. etwas wie...
Hoffe das hilft.
quelle
Hier ist das Beispiel, das das Problem darstellt (vorbereitet in LinQPad - wenn Sie es nicht haben, verwenden Sie es einfach
Console.Writeline
anstelle derDump
Methode):Sowohl x als auch y sind theoretisch gleich und gleich: 0,00001, aber aufgrund mangelnder "unendlicher Genauigkeit" unterscheiden sich diese Werte geringfügig. Leider etwas genug, um
false
beim Vergleich mit 0 auf übliche Weise zurückzukehren.quelle