Sé que normalmente no puedes confiar en la igualdad entre valores de tipo doble o decimal, pero me pregunto si 0 es un caso especial.
Si bien puedo entender imprecisiones entre 0.00000000000001 y 0.00000000000002, 0 en sí mismo parece bastante difícil de estropear, ya que no es nada. Si eres impreciso en nada, ya no es nada.
Pero no sé mucho sobre este tema, así que no me corresponde a mí decirlo.
double x = 0.0;
return (x == 0.0) ? true : false;
¿Eso siempre volverá a ser verdad?
Respuestas:
Es seguro esperar que la comparación regrese
true
si y solo si la variable doble tiene un valor de exactamente0.0
(que en su fragmento de código original es, por supuesto, el caso). Esto es consistente con la semántica del==
operador.a == b
significa "a
es igual ab
".No es seguro (porque no es correcto ) esperar que el resultado de algún cálculo sea cero en aritmética doble (o más generalmente, punto flotante) siempre que el resultado del mismo cálculo en Matemática pura sea cero. Esto se debe a que cuando los cálculos entran en juego, aparece un error de precisión de punto flotante, un concepto que no existe en la aritmética de números reales en matemáticas.
fuente
Si necesita hacer muchas comparaciones de "igualdad", podría ser una buena idea escribir una pequeña función auxiliar o un método de extensión en .NET 3.5 para comparar:
Esto podría usarse de la siguiente manera:
fuente
Para su muestra simple, esa prueba está bien. Pero ¿qué pasa con esto?
Recuerde que .1 es un decimal periódico en binario y no se puede representar con exactitud. Luego compare eso con este código:
Dejaré que ejecute una prueba para ver los resultados reales: es más probable que lo recuerde de esa manera.
fuente
Desde la entrada de MSDN para Double.Equals :
Además, vea Double.Epsilon .
fuente
x.Equals(y)
, entonces(1/x).Equals(1/y)
, pero ese no es el caso six
es0
yy
es1/Double.NegativeInfinity
. Esos valores se declaran iguales, aunque sus recíprocos no lo hacen.x = 0
yy = 0
, y aún así lo encontrarás1/x != 1/y
.x
yy
como tipodouble
? ¿Cómo se comparan los resultados para hacerlos reportar desiguales? Tenga en cuenta que 1 / 0.0 no es NaN.1.0/0.0
no es NaN como debería ser, ya que el límite no es único. En segundo lugar, los infinitos se comparan iguales entre sí, sin prestar atención a los grados de infinito)El problema surge cuando se comparan diferentes tipos de implementación de valor de punto flotante, por ejemplo, comparando float con double. Pero con el mismo tipo, no debería ser un problema.
El problema es que el programador a veces olvida que el tipo implícito de conversión (doble a flotante) está sucediendo para la comparación y resulta en un error.
fuente
Si el número se asignó directamente al flotante o al doble, es seguro realizar la prueba con cero o con cualquier número entero que se pueda representar en 53 bits para un doble o 24 bits para un flotante.
O para decirlo de otra manera, siempre puede asignar un valor entero a un doble y luego comparar el doble con el mismo número entero y tener la garantía de que será igual.
También puede comenzar asignando un número entero y hacer que las comparaciones simples sigan funcionando si se limita a sumar, restar o multiplicar por números enteros (asumiendo que el resultado es menos de 24 bits para un flotante y 53 bits para un doble). Por lo tanto, puede tratar los flotantes y los dobles como números enteros bajo ciertas condiciones controladas.
fuente
No, no está bien. Los denominados valores desnormalizados (subnormales), cuando se comparan igual a 0.0, se compararían como falsos (distintos de cero), pero cuando se usan en una ecuación se normalizarían (se convertirían en 0.0). Por lo tanto, usar esto como un mecanismo para evitar una división por cero no es seguro. En su lugar, agregue 1.0 y compare con 1.0. Esto asegurará que todos los subnormales se traten como cero.
fuente
Pruebe esto y encontrará que == no es confiable para double / float.
double d = 0.1 + 0.2; bool b = d == 0.3;
Aquí está la respuesta de Quora.
fuente
En realidad, creo que es mejor usar los siguientes códigos para comparar un valor doble con 0.0:
Lo mismo para flotador:
fuente