2011-12-20 17 views
7

Sé que es peligroso probar floats para determinar la igualdad debido a errores de precisión, pero ¿es seguro probar cero? Puedo pensar en algunos casos, por ejemplo, en la optimización de casos especiales en algoritmos, donde querría hacer esto. La pregunta es sobre flotadores, pero supongo que la respuesta también se aplica a los dobles.¿Es seguro probar una carroza para una igualdad de 0.0?

Considere el siguiente código:

float factor = calculateFactor(); 
if(factor != 0.0f) 
    applyComplexAlgorithm(factor); 
+0

No acepto las respuestas solo por el hecho de tener una respuesta aceptada en mi pregunta, realmente tiene que haber una respuesta que encuentre responde la pregunta completamente. –

Respuesta

8

Es seguro en el sentido de que si el valor se establece explícitamente en 0.0f, devolverá verdadero ahí.

NO es seguro en el sentido de que no debe esperar que el valor resultante de los cálculos sea exactamente 0.0f.

Así que realmente estás usando 0.0f como un valor de magia especial, no como una comparación real contra cero.

+0

Correcto, fue un mal ejemplo. En este caso, lo que realmente quise decir fue usar 0.0f como un valor especial para comparar, algo que se establecería explícitamente. No sé por qué se me ocurrió este ejemplo, ya que ni siquiera es lo que estoy tratando de hacer. –

+0

Entendido. Sin embargo, evite los valores mágicos espolvoreados con valores "regulares". Duelen la capacidad de descubrimiento (como cuando, cuando observas la firma de la función, no es obvio que te está diciendo otra cosa que no sea el factor) y también lo vuelven más complicado cuando prueban (¡y usan!) La API. En su lugar, intente refactorizar para que esta condición quede expuesta como otra API o al menos sea obvia en la llamada API (la última es menos útil). – supermem613

5

No, no es seguro, ya que el cálculo de calculateFactor() probablemente no dará lugar a 0,0, incluso a través de él aritméticamente debería. Un ejemplo trivial: (0,4 hasta 0,1) -0,3 cuando se hace uso de double resultados en 5.551115123125783e-17

3

Es sin duda segura, pero usted tiene que considerar lo que significa para sus algoritmos. Si su algoritmo usa factor como divisor (y no verifica si divide por cero), entonces sí, es perfectamente razonable verificar factor != 0.0f antes de llamar al applyComplexAlgorithm(factor).

Ahora, independientemente de si debe o no verificar un valor inferior a algunos epsilon antes de usar factor, es totalmente lo que significa su código y no se puede determinar de forma aislada con el código que ha proporcionado.

Si (como mencionó en otro comentario) desea utilizar el valor especial 0.0f como un valor centinela que significa algo específico (como la imposibilidad de calcular un factor), entonces sí, es absolutamente seguro comparar usando ==. Por ejemplo, el uso del siguiente código de 0.0f es determinista y nunca está sujeta a ningún tipo de error de redondeo:

float calculateFactor() 
{ 
    int phase = moon_phase(); 
    if (phase == FULL) { // whatever special case requires returning 0.0f 
     return 0.0f; 
    } else { 
     return 1.0 + (phase * phase); // something that is never 0.0f 
    } 
} 

float factor = calculateFactor(); 
if(factor != 0.0f) 
    applyComplexAlgorithm(factor); 
Cuestiones relacionadas