¿Por qué debería usar el complemento a 2 para comparar dos dobles en lugar de comparar sus diferencias con un valor épsilon?

StackOverflow https://stackoverflow.com/questions/96233

  •  01-07-2019
  •  | 
  •  

Pregunta

Referenciado aquí y aquí... ¿Por qué debería utilizar el complemento a dos en lugar de un método épsilon?Parece que el método épsilon sería suficiente para la mayoría de los casos.


Actualizar: Estoy buscando puramente una razón teórica por la que usarías uno sobre el otro.Siempre he usado el método épsilon.

¿Alguien ha utilizado con éxito la comparación en complemento a 2?¿Por qué?¿Por qué no?

¿Fue útil?

Solución

El segundo enlace al que hace referencia menciona un artículo que tiene una descripción bastante larga del problema:

http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

pero a menos que estés modificando el rendimiento, me quedaría con épsilon para que la gente pueda depurar tu código.

Otros consejos

El método de los bits podría ser más rápido.Digo podría porque en los procesadores modernos (multinúcleo, altamente canalizados) a menudo es imposible adivinar qué es realmente más rápido.Codifique la implementación más simple y obviamente correcta, luego mida y luego optimice.

En resumen, al comparar dos flotadores con orígenes desconocidos, elegir un épsilon que sea válido es casi imposible.

Por ejemplo:

¿Qué es un buen épsilon al comparar la distancia en millas entre Atlanta GA, Dallas TX y algún lugar en Ohio?

¿Qué es un buen épsilon al comparar la distancia en millas entre mi pie izquierdo, mi pie derecho y la computadora debajo de mi escritorio?

EDITAR:

Ok, hay un buen número de personas que no entienden por qué no sabes cuál es tu épsilon.

En los viejos tiempos, escribí dos programas que funcionaban con NeverWinter Nights (un juego creado por BioWare).Uno de los programas tomó un modelo binario y lo convirtió a ASCII.El otro programa tomó un modelo ASCII y lo compiló en binario.Una de las pruebas que escribí fue tomar todos los modelos binarios de BioWare, descompilarlos en ASCII y luego volver a binario.Luego comparé mi versión binaria con la original de BioWare.Uno de los problemas durante la comparación fue lidiar con algunas de las ligeras variaciones en los valores de punto flotante.Entonces, en lugar de crear un montón de EPSILONS diferentes para cada tipo de número de punto flotante (vértice, normal, etc.), quería usar algo como esta comparación de complementos de dos.Evitando así todo el problema de las múltiples EPSILON.

El mismo tipo de problema puede aplicarse a cualquier tipo de software que procese datos de terceros y luego necesite validar sus resultados con el original.En estos casos, es posible que ni siquiera sepas qué representan los valores de punto flotante, sólo tienes que compararlos.Nos encontramos con este problema con nuestro software de automatización industrial.

EDITAR:

LOL, esto ha sido votado a favor y en contra por diferentes personas.

Reduciré el problema a esto, dados dos arbitrario Números de coma flotante, ¿cómo se decide qué épsilon usar?No puedes.

¿Cómo se pueden comparar 1e23 y 1.0001e23 con un épsilon y aún así comparar 1e-23 y 5.2e-23 usando el mismo épsilon?Claro, puedes hacer algunos trucos épsilon dinámicos, pero ese es el objetivo de la comparación de números enteros (que NO requiere que los números enteros sean exactos).

La comparación de enteros es capaz de comparar dos flotantes utilizando un épsilon relativo a la magnitud de los números.

EDITAR

Steve, veamos lo que dijiste en los comentarios:

"Pero sabes lo que significa la igualdad para ti...Por lo tanto, debería poder encontrar un épsilon apropiado".

Dale la vuelta a esta afirmación para decir:

"Si sabes lo que significa la igualdad para ti, entonces deberías poder encontrar un épsilon apropiado".

El objetivo de lo que intento decir es que hay aplicaciones en las que no sabemos qué significa igualdad en sentido absoluto, por lo que tenemos que recurrir a una comparación relativa, que es lo que intenta hacer la versión entera.

Cuando se trata de velocidad, sigue estas reglas:

  1. Si no es un desarrollador con mucha experiencia, no optimice.
  2. Si es un desarrollador experimentado, no optimice todavía.

Haz el método más fácil.

Alex

Óscar tiene razón.No juegues con esto a menos que realmente necesites ese rendimiento.

Y tú no lo haces.Si estuvieras en la situación en la que así fue, no habrías necesitado hacer la pregunta: ya lo sabrías.Si crees que sí, entonces no es así.Sus problemas de rendimiento están en otra parte.Simplemente use la versión legible.

El uso de cualquier método que compare bit a bit generará problemas cuando las fracciones se representen mediante aproximaciones.Todos los números de coma flotante con fracciones que no están denominadas en potencias de dos (1/2, 1/4, 1/8, 1/65536, etc.) son aproximados.También lo son, por supuesto, todos los números irracionales.

tercero flotante = 1/3;flotar dos = 2,0;flotar otro_dos=tercero*6.0;if (two! = other_two) imprime ("¡Aproximación! n");

El único momento en el que la comparación bit a bit funcionaría es cuando se derivan los números de punto flotante exactamente de la misma manera o son representaciones exactas (números enteros, potencias de fracción de dos).Incluso entonces, puede haber múltiples representaciones de algunos números, aunque nunca he visto esto en un sistema que funcione.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top