Lo siento, esta puede ser una pregunta fácil y estúpida, pero necesito saberlo para estar seguro.
Tengo esta if
expresión,
void Foo()
{
System.Double something = GetSomething();
if (something == 0) //Comparison of floating point numbers with equality
// operator. Possible loss of precision while rounding value
{}
}
¿Es esa expresión igual a
void Foo()
{
System.Double something = GetSomething();
if (something < 1)
{}
}
? Porque entonces podría tener un problema al ingresar, if
por ejemplo, con un valor de 0.9.
// Comparison of floating point numbers with equality // operator.
¿Realmente necesitas especificar eso? :)Respuestas:
Bueno, ¿qué tan cerca necesitas que esté el valor de 0? Si pasa por muchas operaciones de punto flotante que en "precisión infinita" pueden resultar en 0, podría terminar con un resultado "muy cercano" a 0.
Por lo general, en esta situación, desea proporcionar algún tipo de épsilon y verificar que el resultado esté dentro de ese épsilon:
if (Math.Abs(something) < 0.001)
El épsilon que debe usar es específico de la aplicación, depende de lo que esté haciendo.
Por supuesto, si el resultado debe ser exactamente cero, una simple verificación de igualdad está bien.
fuente
== 0
. Tienes un literal allí, eso es bastante constante :)Si
something
se ha asignado a partir del resultado de una operación distinta asomething = 0
esa, es mejor que utilice:if(Math.Abs(something) < Double.Epsilon) { //do something }
Editar : este código es incorrecto. Epsilon es el número más pequeño, pero no del todo cero. Cuando desee comparar un número con otro número, debe pensar en cuál es la tolerancia aceptable. Digamos que no le importa nada más allá de .00001. Ese es el número que usarías. El valor depende del dominio. Sin embargo, la mayoría de las veces nunca es Double.Epsilon.
fuente
Math.Abs(0.1f - 0.1d) < double.Epsilon
esfalse
double d = Math.Sqrt(10100)*2; double a = Math.Sqrt(40400); if(Math.Abs(a - d) < double.Epsilon) { Console.WriteLine("true"); }
Tu
something
es undouble
, y has identificado correctamente que en la líneaif (something == 0)
tenemos una
double
en el lado izquierdo (izq.) y unaint
en el lado derecho (der.).Pero ahora parece que cree que lhs se convertirá en an
int
, y luego el==
signo comparará dos enteros. Eso no es lo que pasa. La conversión dedouble
aint
es explícita y no puede ocurrir "automáticamente".En cambio, sucede lo contrario. El rhs se convierte en
double
, y luego el==
signo se convierte en una prueba de igualdad entre dos dobles. Esta conversión es implícita (automática).Se considera mejor (por algunos) escribir
if (something == 0.0)
o
if (something == 0d)
porque entonces es inmediato que estás comparando dos dobles. Sin embargo, eso es solo una cuestión de estilo y legibilidad porque el compilador hará lo mismo en cualquier caso.
También es relevante, en algunos casos, introducir una "tolerancia" como en la respuesta de Jon Skeet, pero esa tolerancia también lo sería
double
. Por supuesto, podría serlo1.0
si quisiera, pero no tiene que ser un entero [el menos estrictamente positivo].fuente
Si simplemente desea suprimir la advertencia, haga esto:
if (something.Equals(0.0))
Por supuesto, esta es solo una solución válida si sabe que la deriva no es un problema. A menudo hago esto para comprobar si estoy a punto de dividir por cero.
fuente
No creo que sea igual, honestamente. Considere su propio ejemplo: algo = 0,9 o 0,0004. En el primer caso será FALSO, en el segundo caso será VERDADERO. Al tratar con estos tipos, suelo definir para mí el porcentaje de precisión y comparar dentro de esa precisión. Depende de tus necesidades. algo como...
if(((int)(something*100)) == 0) { //do something }
Espero que esto ayude.
fuente
Aquí está el ejemplo que presenta el problema (preparado en LinQPad; si no lo tiene, use en
Console.Writeline
lugar delDump
método):void Main() { double x = 0.000001 / 0.1; double y = 0.001 * 0.01; double res = (x-y); res.Dump(); (res == 0).Dump(); }
Tanto x como y son teóricamente iguales e iguales a: 0,00001 pero debido a la falta de "precisión infinita", esos valores son ligeramente diferentes. Desafortunadamente, lo suficientemente leve como para regresar
false
cuando se compara con 0 de la manera habitual.fuente