Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I get Java to throw an exception when doing a comparison between floats when one of them turns out to be NaN?

I spent about 2 hours tracking down a bug today and I would've found it much quicker had java thrown an exception when comparing NaN with a float. It would be nice if I could protect myself from this in the future. Any help is appreciated.

like image 951
Xavier Avatar asked Feb 13 '11 20:02

Xavier


People also ask

How do you decide if an exception should be thrown in a method?

An exception should be thrown when a function experiences a failure, i.e., an error. A function is a unit of work, and failures should be viewed as errors or otherwise based on their impact on functions.

How do you throw an exception to another method in Java?

Using the Throws keyword Throws is a keyword used to indicate that this method could throw this type of exception. The caller has to handle the exception using a try-catch block or propagate the exception. We can throw either checked or unchecked exceptions.

Which methods can throw an exception?

All methods use the throw statement to throw an exception. The throw statement requires a single argument: a throwable object. Throwable objects are instances of any subclass of the Throwable class.

What type of exception should I throw Java?

Only checked exceptions are required to be thrown using the throws keyword. Unchecked exceptions don't need to be thrown or handled explicitly in code.


2 Answers

The JVM instruction set reference specifically disallows the byte codes that do floating point math from throwing exceptions and rigidly specifies how they should work when NaN is an operand. If there is a way to do this, it will either require you to explicitly throw exceptions on NaN or to use a custom compiler to insert these checks for you.

One option that might be helpful would be to write a function like this:

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

With this, you can write code to this effect:

float f = check(myOtherFloat / yetAnotherFloat);

This will then do the computation and throw on an error. Ideally with a short function name it won't be too obtrusive.

W

like image 70
templatetypedef Avatar answered Oct 17 '22 14:10

templatetypedef


The protection in float or double is to make the result NaN or false. If you want to detect NaN, you are better of preventing the value in the first place e.g 0/0. When you do a division, check for 0 as a divisor and throw an Exception if it is. You can wrap this with a helper method to simplify.

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

If I know the value could be 0 or more only, I often add a bias like

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

This never produces NaN provided b >= 0. If a == 0, d == 0. The bias to use depends on the situation.

like image 2
Peter Lawrey Avatar answered Oct 17 '22 12:10

Peter Lawrey