Est-il sûr de vérifier les valeurs à virgule flottante pour l'égalité à 0?
Je sais que vous ne pouvez pas compter sur l'égalité entre les double ou décimal des valeurs du type normalement, mais je me demandais si 0 est un cas particulier.
Même si je peux comprendre les imprécisions entre 0.00000000000001 et 0.00000000000002, 0 lui-même semble assez difficile de désordre, car il est tout simplement rien. Si vous êtes imprécise sur rien, c'est pas rien de plus.
Mais je ne sais pas beaucoup sur ce sujet, il n'est donc pas pour moi de dire.
double x = 0.0;
return (x == 0.0) ? true : false;
Qui va toujours retourner vrai?
- L'opérateur ternaire est redondante dans ce code 🙂
- LOL vous avez raison. Aller moi
- Je ne voudrais pas le faire parce que vous don t savent comment x s'est mis à zéro. Si vous voulez le faire, vous voudrez probablement le rond ou le plancher x pour se débarrasser de la 1e-12 ou tels qui pourraient être marqué sur la fin.
Vous devez vous connecter pour publier un commentaire.
Il est sûr de s'attendre à ce que la comparaison sera de retour
true
si et seulement si la variable de type double a une valeur d'exactement0.0
(ce qui, dans l'original de votre extrait de code est, bien sûr, le cas). Ceci est cohérent avec la sémantique de la==
de l'opérateur.a == b
signifie "a
est égal àb
".Il est pas sûr (parce que c'est pas correct) de s'attendre à ce que le résultat de certains calculs sera de zéro en double (ou plus généralement, à virgule flottante) l'arithmétique à chaque fois que le résultat d'un calcul dans le domaine des Mathématiques pures, c'est zéro. C'est parce que lorsque les calculs dans le sol, précision en virgule flottante d'erreur s'affiche - un concept qui n'existe pas dans le nombre Réel arithmétique en Mathématiques.
Si vous avez besoin de faire beaucoup de "l'égalité" des comparaisons, il pourrait être une bonne idée d'écrire une petite aide de la fonction ou de la méthode d'extension dans .NET 3.5 pour comparer:
Cela pourrait être utilisé de la manière suivante:
Pour votre simple échantillon, le test est ok. Mais ce:
Rappelez-vous que le .1 est une répétition de décimal en binaire et ne peuvent pas être représentés exactement. Puis de les comparer à ce code:
Je vais vous laisser exécuter un test pour voir les résultats réels: vous êtes plus susceptibles de se rappeler de cette façon.
De la MSDN entrée pour Double.Est égal à:
Aussi, voir Double.Epsilon.
x.Equals(y)
, puis(1/x).Equals(1/y)
, mais ce n'est pas le cas six
est0
ety
est1/Double.NegativeInfinity
. Ces valeurs déclarer que l'égalité, même si leurs valeurs réciproques ne le font pas.x = 0
ety = 0
, et vous souhaitez toujours trouver que1/x != 1/y
.x
ety
typedouble
? Comment comparez-vous les résultats de rapports inégaux? Notez que 1/0.0 n'est pas NaN.1.0/0.0
ne parvient pas à être NaN comme il se doit, la limite n'est pas unique. En second lieu, que les infinis comparer égale les unes des autres, sans prêter attention à des degrés de l'infini)x*x == x
quand il ne devrait vraiment pas être (infinities doit être ordonné à l'égard de tous les finis de nombres et de leur homologue de signe opposé, mais non ordonnée à l'égard d'un autre infini du même signe).isfinite(x)? x == y : fpclassify(x) == fpclassify(y)
pour les relations d'équivalence (ce serait bien d'avoir une fonction standard pour ce faire, assurez-vous). Mais étant donné quex == x
est faux pour NaN, il semble clair qu'il devrait aussi être faux pour les autres non-fini les cours.Le problème vient quand vous comparez les différents types de valeur à virgule flottante de la mise en œuvre par exemple en comparant flotteur avec le double. Mais de même type, il ne devrait pas être un problème.
Le problème est, le programmeur oublie parfois qu'implicite de type cast (double float) qui se passe pour la comparaison et la c'est un bug.
Si le nombre a été directement attribué à l'float ou double, il est prudent de tester contre zéro ou un nombre entier quelconque qui peut être représenté dans 53 bits pour un lit double ou 24 bits pour un float.
Ou pour le dire d'une autre façon, vous pouvez toujours affecter et de la valeur entière d'un double, puis de comparer le double retour à la même entier et être garanti qu'il sera égal.
Vous pouvez également commencer par l'attribution d'un nombre entier et d'avoir des comparaisons simples de continuer à travailler en collant à l'addition, la soustraction ou la multiplication par des nombres entiers (en supposant que le résultat est inférieur à 24 bits pour un float abd 53 bits pour une double). Vous pouvez donc traiter des flotteurs et des doubles que des entiers, sous certaines conditions contrôlées.
Non, il n'est pas OK. Soi-disant dénormalisée valeurs (subnormale), comparativement égal à 0.0, de comparer, comme fausse (non-nulle), mais lorsqu'il est utilisé dans une équation serait normalisée (devenir 0.0). Ainsi, l'utilisation de ce comme un mécanisme permettant d'éviter une division par zéro n'est pas sûr. Au lieu de cela, ajouter 1,0 et de les comparer à 1.0. Cela permettra d'assurer que tous les subnormals sont considéré comme égal à zéro.
Essayez, et vous verrez que == n'est pas fiable pour double/float.
double d = 0.1 + 0.2;
bool b = d == 0.3;
Ici est la réponse de Quora.
En fait, je pense qu'il est préférable d'utiliser les codes suivants pour comparer une valeur double contre 0,0:
Même pour float: