c# - normalizada - numeros de punto flotante de 64 bits
¿Puedes comparar los valores de punto flotante exactamente a cero? (8)
Sé que no podemos comparar 2 valores de punto flotante utilizando ==. Solo podemos comparar que están dentro de algún intervalo entre sí. Lo sé
if(val == 0.512)
es incorrecto debido a errores inherentes en los cálculos de punto flotante y la conversión a binario y debe ser
if (val in (0.512-epsilon, 0.512+epsilon))
Pero es 0 especial? ¿Podemos comparar flotadores exactamente a 0? ¿O incluso eso es incorrecto? Particularmente en el contexto de C # y Java?
double val = 0;
val = getVal();
if(val == 0)
A pesar de que 0 tiene una representación exacta, no puede confiar en que el resultado de un cálculo que usa flotantes sea exactamente 0. Como señaló, esto se debe al cálculo de punto flotante y los problemas de conversión.
Por lo tanto, debe probar para 0 contra su tolerancia épsilon.
Debido a que cero tiene una representación exacta, es posible que un valor se compare == con cero. Si la variable que está probando fue establecida por una asignación, o por un valor ingresado (como getVal en su ejemplo?), Fácilmente podría ser cero. Pero si fue el resultado de un cálculo, las posibilidades de que sea exactamente cero son muy pequeñas. Esto se agrava porque las fracciones decimales ordinarias como 0.2 no tienen una representación exacta en punto flotante. Por eso es mejor usar epsilon.
En cualquier situación no trivial, realmente solo debe utilizar el enfoque de tolerancia. Como se señaló, la comparación de cero solo es precisa cuando en realidad la asignó a cero.
Sin repetir lo que otros han dicho, solo quiero enfatizar el hecho de que usar el enfoque de la tolerancia es más una prueba de futuro . Lo que una vez piensas que es una tarea simple puede involucrar aritmética real más tarde. El uso de una comparación desnuda hace que sea dolorosamente oscuro depurar en una fecha posterior.
No creo que pueda, en general, el cálculo que se produce en getVal () puede resultar lógicamente en cero, pero eso no significa que devolverá cero. Si explícitamente devuelve un cero para indicar alguna condición, la comparación siempre debería funcionar, pero no creo que sea la mejor práctica. Me gustaría modificar la función para devolver un código de estado y pasar el valor que se cambiará por ref.
Para la comparación con err todo lo que necesitas es.
// compare a and b with an ERR error.
if (Math.abs(a - b) <= ERR)
Comparar con 0
// compare a and 0 with an ERR error.
if (Math.abs(a) <= ERR)
Puedes comparar a cero si asignaste esa variable a cero. Si obtienes cero de por ejemplo. una resta puede obtener un número muy pequeño cerca de cero. Ej .: 0.1-0.1 puede evaluar algo como 1e-9.
Todavía recomendaría seguir el lenguaje de tolerancia y no compararlo exactamente con cero.
Utilice el enfoque de tolerancia / efsilon.
Acabo de evaluar lo siguiente en Java, que da como resultado matemáticamente cero:
1.0/5.0 + 1.0/5.0 - 1.0/10.0 - 1.0/10.0 - 1.0/10.0 - 1.0/10.0
y en realidad consiguió
2.7755575615628914E-17