2011-02-13 15 views
5

Pasé cerca de 2 horas rastreando un error hoy y lo habría encontrado mucho más rápido si Java hubiera lanzado una excepción al comparar NaN con un flotador. Sería bueno si pudiera protegerme de esto en el futuro. Cualquier ayuda es apreciada.¿Puedo hacer que Java arroje una excepción al hacer una comparación entre carrozas cuando una de ellas resulta ser NaN?

+1

Suena como que necesita una señalización NaN (SNAN), pero sospecho que no es posible. – Gabe

+0

De hecho, [Java no es compatible con la comparación de señalización] (http://java.sun.com/docs/books/jvms/second_edition/html/Overview.doc.html#35254). –

Respuesta

5

El JVM instruction set reference específicamente no permite que los códigos de bytes que hacen matemática de coma flotante arrojen excepciones y especifica rígidamente cómo deberían funcionar cuando NaN es un operando. Si hay una forma de hacerlo, o bien le pedirá que explícitamente lanzar excepciones en NaN o utilizar un compilador personalizado para insertar estos controles por usted.

Una opción que podría ser útil sería escribir una función como esta:

public static float check(float value) { 
    if (Float.isNaN(value)) 
     throw new ArithmeticException("NaN"); 
    return value; 
} 

Con esto, se puede escribir código para este efecto:

float f = check(myOtherFloat/yetAnotherFloat); 

Esto luego hacer el cómputo y lanzar un error. Idealmente con un nombre de función corto, no será demasiado molesto.

W

2

La protección en flotante o doble es hacer que el resultado sea NaN o falso. Si desea detectar NaN, es mejor que evite el valor en primer lugar, por ejemplo, 0/0. Cuando haces una división, busca 0 como un divisor y lanza una excepción si es así. Puede envolver esto con un método de ayuda para simplificar.

public static double div(double a, double b) { 
    if(b == 0) throw new IllegalArguementException(); 
    return a/b; 
} 

Si sé que el valor puede ser 0 o más solamente, a menudo añadir un sesgo como

double d = a/(b + 1e-9); 

Esto nunca produce NaN proporcionó b> = 0. Si a == 0, d = = 0. El sesgo a usar depende de la situación.

+0

Me gusta esta idea, pero ¿qué hay de la multiplicación del infinito por cero? ¿Harías lo mismo durante la multiplicación? – templatetypedef

+1

Buen punto. Quizás puedas evitar tener el infinito. –

Cuestiones relacionadas