Como otros han dicho, este es sólo un problema fundamental que se obtiene cuando se hace de punto flotante aritmética a cualquier base. Simplemente sucede que base-2 es el más común en las computadoras (porque admite una implementación eficiente del hardware).
La mejor solución, si es posible, es cambiar a usar algún tipo de representación de cociente del número para su bucle, haciendo que el valor de coma flotante se derive de eso. OK, eso suena exagerado! Para su caso específico, me gustaría escribir como:
int dTimes10 = 20;
double d;
while(dTimes10 != 0) {
dTimes10 -= 2;
d = dTimes10/10.0;
}
Aquí, realmente estamos trabajando con fracciones [20/10, 18/10, 16/10, ..., 2/10, 0/10] donde la iteración se hace con números enteros (es decir, fáciles de corregir) en el numerador con un denominador fijo, antes de convertir a coma flotante. Si puede reescribir sus iteraciones reales para que funcionen de esta manera, tendrá un gran éxito (y en realidad no son mucho más costosas que lo que estaba haciendo antes, lo cual es una gran compensación para obtener la corrección).
Si no puede hacer esto, necesita usar equal-in-epsilon como su comparación. Aproximadamente, eso reemplaza a d != target
con abs(d - target) < ε
, donde la selección de ε (epsilon) a veces puede ser incómoda. Básicamente, el valor correcto de ε depende de un grupo de factores, pero es mejor que se seleccione como 0.001 para la iteración de ejemplo dada la escala del valor del paso (es decir, es medio por ciento de la magnitud del paso, por lo que cualquier elemento dentro de eso va a ser un error en lugar de informativo).
Nunca use '==' con valores flotantes. Tal vez usar algo como 'f> epsilon'. – pascal
[Habían pasado unos días, supongo que estábamos por vencer.] (Http://docs.sun.com/source/806-3568/ncg_goldberg.html) – GManNickG
En Java, creo que existe el modificador "Strictfp" para tales situaciones –