Désolé, c'est peut-être une question stupide facile, mais j'ai besoin de savoir pour être sûr.
J'ai cette if
expression,
void Foo()
{
System.Double something = GetSomething();
if (something == 0) //Comparison of floating point numbers with equality
// operator. Possible loss of precision while rounding value
{}
}
Cette expression est-elle égale à
void Foo()
{
System.Double something = GetSomething();
if (something < 1)
{}
}
? Parce qu'alors je pourrais avoir un problème, en entrant le if
avec par exemple une valeur de 0,9.
// Comparison of floating point numbers with equality // operator.
Aviez-vous vraiment besoin de le préciser? :)Réponses:
Eh bien, à quel point avez-vous besoin que la valeur soit proche de 0? Si vous effectuez un grand nombre d'opérations en virgule flottante qui, en "précision infinie", peuvent donner 0, vous pourriez vous retrouver avec un résultat "très proche" de 0.
En règle générale, dans cette situation, vous souhaitez fournir une sorte d'epsilon et vérifier que le résultat se trouve juste dans cet epsilon:
if (Math.Abs(something) < 0.001)
L'epsilon que vous devez utiliser est spécifique à l'application - cela dépend de ce que vous faites.
Bien sûr, si le résultat doit être exactement zéro, alors un simple contrôle d'égalité convient.
la source
== 0
. Vous avez un littéral là - c'est assez constant :)Si
something
a été attribué à partir du résultat d'une opération autre que,something = 0
il vaut mieux utiliser:if(Math.Abs(something) < Double.Epsilon) { //do something }
Edit : Ce code est faux. Epsilon est le plus petit nombre, mais pas tout à fait zéro. Lorsque vous souhaitez comparer un nombre à un autre, vous devez réfléchir à la tolérance acceptable. Disons que tout ce qui dépasse .00001 ne vous préoccupe pas. C'est le numéro que vous utiliseriez. La valeur dépend du domaine. Cependant, ce n'est certainement jamais Double.Epsilon.
la source
Math.Abs(0.1f - 0.1d) < double.Epsilon
estfalse
double d = Math.Sqrt(10100)*2; double a = Math.Sqrt(40400); if(Math.Abs(a - d) < double.Epsilon) { Console.WriteLine("true"); }
Votre
something
est undouble
, et vous l'avez correctement identifié dans la ligneif (something == 0)
nous avons un
double
sur le côté gauche (lhs) et unint
sur le côté droit (rhs).Mais maintenant, il semble que vous pensez que le lhs sera converti en un
int
, puis le==
signe comparera deux entiers. Ce n'est pas ce qui arrive. La conversion dedouble
àint
est explicite et ne peut pas se faire "automatiquement".Au lieu de cela, le contraire se produit. Le rhs est converti en
double
, puis le==
signe devient un test d'égalité entre deux doubles. Cette conversion est implicite (automatique).Il est préférable (par certains) d'écrire
if (something == 0.0)
ou
if (something == 0d)
car alors c'est immédiat que vous comparez deux doubles. Cependant, ce n'est qu'une question de style et de lisibilité car le compilateur fera la même chose dans tous les cas.
Il est également pertinent, dans certains cas, d'introduire une «tolérance» comme dans la réponse de Jon Skeet, mais cette tolérance en serait une
double
aussi. Cela pourrait bien sûr l'être1.0
si vous le vouliez, mais il n'est pas nécessaire que ce soit l'entier [le moins strictement positif].la source
Si vous souhaitez simplement supprimer l'avertissement, procédez comme suit:
if (something.Equals(0.0))
Bien sûr, ce n'est une solution valable que si vous savez que la dérive n'est pas un problème. Je fais souvent cela pour vérifier si je suis sur le point de diviser par zéro.
la source
Je ne pense pas que ce soit égal, honnêtement. Prenons votre propre exemple: quelque chose = 0,9 ou 0,0004. Dans le premier cas, ce sera FALSE, dans le second cas, ce sera VRAI. En traitant avec ces types, je définis généralement pour moi un pourcentage de précision et je compare dans cette précision. Dépend de vos besoins. quelque chose comme...
if(((int)(something*100)) == 0) { //do something }
J'espère que cela t'aides.
la source
Voici l'exemple présentant le problème (préparé dans LinQPad - si vous ne l'avez pas, utilisez simplement à la
Console.Writeline
place de laDump
méthode):void Main() { double x = 0.000001 / 0.1; double y = 0.001 * 0.01; double res = (x-y); res.Dump(); (res == 0).Dump(); }
Les deux x et y sont théoriquement identiques et égaux à: 0,00001 mais en raison du manque de «précision infinie», ces valeurs sont légèrement différentes. Malheureusement un peu assez pour revenir
false
en comparant à 0 de manière habituelle.la source