Comme d'autres l'ont dit, cela est juste un problème fondamental que vous obtenez lorsque vous faites à virgule flottante arithmétique à toute base. Il se trouve que base-2 est le plus commun dans les ordinateurs (car il admet une implémentation matérielle efficace).
La meilleure solution, si possible, est de passer à l'utilisation d'une représentation quotient du nombre pour votre bouclage, ce qui en déduit la valeur à virgule flottante. OK, ça a l'air exagéré! Pour votre cas, je l'écris comme:
int dTimes10 = 20;
double d;
while(dTimes10 != 0) {
dTimes10 -= 2;
d = dTimes10/10.0;
}
Ici, nous travaillons vraiment avec des fractions [20/10, 18/10, 16/10, ..., 2/10, 0/10] où l'itération est faite avec des entiers (c'est-à-dire faciles à obtenir correctement) dans le numérateur avec un dénominateur fixe, avant de convertir en virgule flottante. Si vous pouvez réécrire vos réelles itérations pour qu'elles fonctionnent comme ceci, vous aurez beaucoup de succès (et elles ne sont vraiment pas beaucoup plus chères que ce que vous faisiez auparavant, ce qui est un bon compromis pour obtenir l'exactitude).
Si vous ne pouvez pas faire cela, vous devez utiliser equal-within-epsilon comme comparaison. Approximativement, cela remplace d != target
avec abs(d - target) < ε
, où la sélection de ε (epsilon) peut parfois être maladroite. Fondamentalement, la bonne valeur de ε dépend d'un tas de facteurs, mais c'est probablement mieux choisi comme 0.001 pour l'itération d'exemple étant donné l'échelle de la valeur d'étape (c'est-à-dire, c'est un demi-pour cent de l'amplitude de l'étape, donc tout ce qui va être erreur plutôt qu'informatif).
N'utilisez jamais '==' avec des valeurs flottantes. Peut-être utiliser quelque chose comme «f> epsilon». – pascal
[Cela faisait quelques jours, je suppose que nous étions en retard.] (Http://docs.sun.com/source/806-3568/ncg_goldberg.html) – GManNickG
En Java, je pense qu'il y a le modificateur "Strictfp" pour de telles situations –