2010-09-08 15 views
6

En mi máquina, y la versión .net actual Math.exp (-1000) devuelve 0.0, como es razonable porque es un número que es demasiado pequeño para representarlo como un doble.Math.Exp del número negativo grande

¿Puedo confiar en esto para seguir siéndolo en otras máquinas y en futuras construcciones .net? Msdn me dice Math.exp (Double.NegativeInfinity) devuelve 0.0 (que, por lo tanto, espero seguir así en el futuro), pero ¿qué pasa con -1000?

Respuesta

4

La función Math.Exp() se define como que funciona con tipos de precisión doble. Tenga en cuenta que exp (-1000) == 5.08e-435, muy por debajo del valor absoluto más pequeño que se puede expresar en un doble.

Creo que es seguro decir que en cualquier entorno donde se usen los números flotantes IEEE, exp(-1000) será 0.0. Es muy poco probable que .Net alguna vez abandone el punto flotante IEEE. En términos más generales, supongo que le interesa saber si las cantidades pequeñas son prácticamente nulas. En resumen, sí, en IEEE.

Sin embargo, probablemente sea mejor no diseñar este comportamiento en su código. Como sugiere Darin, compare valores de coma flotante dentro de una tolerancia. Si tiene una razón para trabajar con números muy pequeños o grandes, considere rastrear la cantidad como un logaritmo y realizar operaciones en el dominio logarítmico (si necesita multiplicar, agregar los logaritmos, etc.). Puede utilizar una biblioteca matemática de alta precisión, pero incluso con esos números a medida que los números se vuelven muy pequeños, el cálculo puede estar sujeto a grandes errores de redondeo y poca estabilidad numérica.

Finalmente, si su intención es calcular 1.0 - Math.Exp(-num) o Math.Exp(-num) - 1, busque una función de biblioteca que las calcule directamente para obtener la mejor precisión.

2

No, nunca se puede confiar en que una variable del tipo double sea exactamente igual a algo. Nunca escriba algo como esto. Nunca utilice el operador == para comparar dos operandos dobles:

double d = ... 
if (d == 0.0) { 

} 

su lugar debe definir una precisión deseada y siempre trabajar con esta precisión:

double epsilon = 1e-5; 
double d = ... 
if (Math.Abs(d - 0.0) < epsilon) { 

} 
+0

¿Alguna razón para el voto a favor? Por favor, deje un comentario cuando downvoting. –

1

Utilice el built-in construcción que se han indicado.

Debería permanecer así debido a las limitaciones de tamaño con respecto a un doble, pero preferiría el uso de la constante incorporada a la clase y confirmada por MSDN.

+0

¿A qué te refieres exactamente con la construcción incorporada? – willem

+0

@Willem - Me refería a usar 'Double.NegativeInfinity', en lugar de un número mágico si es posible para las operaciones de límite. –

1

No, nunca es una buena idea recordar una excepción como esa. No es una excepción lanzada, pero el hecho de que es demasiado pequeño para mostrar y por lo tanto solo te da 0.0 es una excepción. Es mejor quedarse con constantes para algo así.

+0

Fuente de cita? No veo ninguna razón para creer que hay una excepción. – recursive

+0

no es una excepción en el sentido tradicional, sino más bien el hecho de que el tipo de variable no puede manejar el número por lo que da el valor predeterminado de 0.0 Después de todo, una excepción no es más que algo que su código no puede manejar. – Adkins

Cuestiones relacionadas