Pourquoi le résultat est différent de ce problème?
-
05-09-2019 - |
Question
Je suis tombé sur ce problème d'arithmétique suivante.
Mais le résultat est différent de l'opération mathématique normale, Pourquoi est-il?
double d1 = 1.000001;
double d2 = 0.000001;
Console.WriteLine((d1-d2)==1.0);
La solution
Je suppose que vous avez trouvé la question sur la page Brainteasers Jon Skeet? Les réponses sont listées et expliquées sur le même site.
Pour une question de référence, voici la réponse copiée à partir de cette page.
3) arithmétique de Silly
Les ordinateurs sont destinés à être bon à l'arithmétique, sont-ils pas? Pourquoi cette impression « Faux »?
double d1 = 1.000001; double d2 =
0.000001; Console.WriteLine((d1-d2)==1.0);
Réponse: Toutes valeurs ici sont stockées sous forme binaire en virgule flottante. Bien que 1.0 peuvent être stockées exactement, 1,000001 est stockée comme 1,0000009999999999177333620536956004798412322998046875 et 0,000001 est stockée comme 0,000000999999999999999954748111825886258685613938723690807819366455078125. La différence entre eux est pas exactement 1,0, et en fait la différence ne peut pas être stocké exactement non plus.
Autres conseils
A partir de l'entrée MSDN pour Double.Equals :
Précision dans les comparaisons
La méthode Equals doit être utilisé avec la prudence, parce que deux apparemment des valeurs équivalentes peuvent être inégales en raison à la précision différente des deux valeurs. Les rapports exemple suivant que la valeur double 0,3333 et la Double retourné en divisant 1 par 3 sont inégale.
...
Plutôt que de comparer l'égalité, une technique recommandée implique la définition d'une marge acceptable de différence entre deux valeurs (telles que 0,01% de l'une des valeurs). Si la La valeur absolue de la différence entre les deux valeurs est inférieur ou égale à cette marge, la différence est susceptible d'être due à des différences de précision et, par conséquent, les valeurs sont susceptibles d'être égaux. Le suivant exemple utilise cette technique pour comparer .33333 et 1/3, les deux valeurs doubles que l'exemple de code précédent trouvé être inégale.
Si vous devez faire beaucoup de comparaisons « l'égalité », il pourrait être une bonne idée d'écrire une petite fonction d'aide ou méthode d'extension .NET 3.5 pour comparer:
public static bool AlmostEquals(this double double1, double double2, double precision)
{
return (Math.Abs(double1 - double2) <= precision);
}
Cela pourrait être utilisé de la manière suivante:
double d1 = 1.000001;
double d2 = 0.000001;
bool equals = (d1 - d2).AlmostEquals(1.0, 0.0000001);
Voir cette question très similaire: C # .NET: Est-il sûr de vérifier les valeurs à virgule flottante pour l'égalité à 0
?Il est parce que les ordinateurs font les mathématiques dans la base 2, et par conséquent beaucoup de nombres à virgule flottante décimaux ne peut pas être représenté exactement avec un nombre limité de chiffres.
Parce que vous utilisez des nombres à virgule flottante.
Si vous faites cette arithmétique dans votre application, le decimal
type doit être utilisé
decimal d1 = 1.000001M;
decimal d2 = 0.000001M;
Console.WriteLine((d1 - d2) == 1.0M); // evaluates as true
cela peut être dû à des problèmes de précision flottante de point, car il se pourrait que votre résultat est pas exactement 1.0 mais peut-être quelque chose comme 1,000000000001
Cela se produit parce que les types de virgule flottante enregistre des numéros en utilisant une base de deux et non une représentation de base dix. Ceci a pour conséquence que le double est incapable de stocker des valeurs telles que 0,1 exactement. Par exemple 0,1 est représentée par la valeur unique ,100000001490116119384765625.
Vous devez utiliser décimal pour se débarrasser de l'erreur.
Ceci est dû à la façon dont les nombres à virgule flottante travaillent dans le CPU, ce n'est pas C # spécifique. Voir cette entrée de Wikipedia et le papier ici pour plus d'informations.
La réponse courte est que les nombres à virgule flottante ne sont pas stockées sous la forme d'une représentation exacte, faisant une comparaison avec « == » ne fonctionne pas dans la façon dont vous essayez de l'utiliser.
Voyez ce que docs python doit Saym le problème est le même pour les deux: