En mi simulación numérica Tengo un código similar al del siguiente fragmento¿Cómo lidiar con el exceso de precisión en los cálculos de coma flotante?
double x;
do {
x = /* some computation */;
} while (x <= 0.0);
/* some algorithm that requires x to be (precisely) larger than 0 */
Con ciertos compiladores (por ejemplo gcc) en ciertas plataformas (por ejemplo, Linux, x87 matemáticas) es posible que x
se calcula superior al doble precisión ("con precisión excesiva"). (Actualización: Cuando hablo de precisión aquí, me refiero a precisión/y/rango.) En estas circunstancias es concebible que la comparación (x <= 0
) devuelva falso aunque la próxima vez que x se redondea a precisión doble se vuelva 0 . (Y no hay garantía de que x no se redondea hacia abajo en un punto arbitrario en el tiempo.)
¿hay alguna manera de realizar esta comparación que
- es portátil,
- obras en código que se inserta,
- no tiene ningún impacto en el rendimiento t y
- no excluye algún rango arbitrario (0, eps)?
Intenté usar (x < std::numeric_limits<double>::denorm_min()
) pero eso pareció ralentizar significativamente el ciclo cuando se trabajaba con matemáticas SSE2. (Sé que denormals pueden ralentizar un cálculo, pero no me esperaba que sean más lentos en movimiento justo alrededor y comparar.)
Actualización: Una alternativa es utilizar volatile
a la fuerza en la memoria antes x
la comparación, por ejemplo escribiendo
} while (*((volatile double*)&x) <= 0.0);
Sin embargo, dependiendo de la aplicación y las optimizaciones aplicadas por el compilador, esta solución puede introducir un rendimiento evidente también.
Actualización: El problema con cualquier tolerancia es que es bastante arbitraria, es decir, que depende de la aplicación o contexto específico. Preferiría hacer la comparación sin demasiada precisión, para no tener que hacer suposiciones adicionales o introducir algunos epsilons arbitrarios en la documentación de las funciones de mi biblioteca.
Pregunta interesante, la primera vez que he oído hablar de alguien quejándose de demasiada precisión. – dsimcha
¿Qué sucede cuando agrega un molde explícito a la comparación, es decir, '((double) x) <= 0.0'? – Christoph
Quizás también sea relevante: http://stackoverflow.com/questions/322797/problem-with-floating-point-precision-when-moving-from-i386-to8x4 – Christoph