14

My question is about try-catch blocks on a simple division by zero example. You see the first line of try? If I cast any of those two variables to the double the program does not recognize the catch block. In my opinion, whether I cast or not only the catch block must be executed. What is wrong on this code?

public static void main(String[] args) {

    int pay=8,payda=0;  

    try {

        double result=pay/(double)payda; // if I cast any of the two variables, program does not recognize the catch block, why is it so?
        System.out.println(result);
        System.out.println("inside-try");

    } catch (Exception e) {

        System.out.println("division by zero exception");
        System.out.println("inside-catch");

    }
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Firat
  • 141
  • 1
  • 1
  • 3

7 Answers7

24

Divide by zero is valid for floating point numbers.

  • 1/0 yields Infinity.
  • (-1)/0 yields -Infinity.
  • 0/0 yields NaN.

These "numbers" are properly defined in IEEE 754.

Integer division by zero, on the other hand, throws because one cannot represent infinity as an int.

kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • If floating point division cannot throw an exception, then the try / catch should be removed and error codes used instead. – Hamish Grubijan Feb 14 '10 at 02:30
  • 1
    I don't think `int` throws because it can't represent infinity. 1/0 is simply meaningless, and that's why it throws. Floating point, on the other hand, did some hand-waving and said "it should be infinity". – GManNickG Feb 15 '10 at 19:57
14

I'd suggest verifying:

if (divisor != 0) {
    // calculate
}

rather than catching an exception

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • 1
    Unless divisor is integer, non-zero divisors can easily produce unusable results, like a large denom and small divisor: "Double div=Double.MAX_VALUE/0.5;" yields Infinity. I recommend checking Double.isInfinite and Double.isNaN (or the Float equivalents) on any risky calculation over checking divisor != 0. – Steve Zobell Feb 05 '16 at 19:09
  • assumption was they are integers, as in the example above – Bozho Feb 16 '16 at 14:34
8

Since you are a self-proclaimed "newbie", I think it would be a good idea to point out some broader issues with your code. (I know it is not production code, but just lets assume for the sake of argument that it was.)

  • If an exception is expected, it is usually simpler, clearer and more efficient if you detect the condition that will give rise to the exception. In this case, if you expect divisor to occasionally be zero it is better to test it before doing the division.

  • On the other hand, if an exception is totally unexpected (i.e. a "bug") the best strategy is to let the exception propagate to the outermost level. At that point your application catch should catch all exceptions, log the exception stacktrace and bail out.

  • Apart from the previous bullet, it is a bad idea to catch Exception, RuntimeException, Throwable or Error. Doing this will catch a large number of exceptions that you probably don't intend to catch. In this case, since you are expecting an ArithmeticException, you should catch just that.

  • It is rarely correct to use float or double in financial applications. These types are not exact, but financial applications typically require quantities of money to be handled exactly.

  • More generally, floating point numbers are inherently hard for lay people (and newbies) to understand. A lot of the "truths" that people expect to hold actually don't hold. For example, a floating point calculation of 1.0/3.0 + 1.0/3.0 + 1.0/3.0 does not give 1.0. Similarly (as you discovered) division by zero behaves differently. If you want to use floating point safely, you need to understand the pitfalls.

EDIT elaborating the first point in response to @Jay's comment.

First, I deliberately used the word "usually". There are cases where avoiding throwing the expected exception achieves nothing.

Having said that, you often don't want a generic "expected" exception to happen even if your application cannot deal with the situation immediately. For example, if the OP's code was part of something larger, it may be better to explicitly throw IllegalArgumentException (if this is a violation of an API contract) or some checked UserEnteredRubbishException if we know that this is a result of bad user input (and there is some opportunity to report / correct it).

The fact that we are "expecting" an exception means by definition that we know more about it than (say) a generic ArithmeticException would say. If we allow a generic exception to propagate, it makes it harder for a catch block many stack frames to act appropriately. In this case for example, the remote catch block could not diagnose the cause of the divide-by-zero with any certainty. The ArithmeticException might have come from a different part of the application, and might not even be a divide-by-zero! The way to address is to explicitly throwing a more specific exception.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • I'd quibble with your first point. If a special case is expected AND there is something you can do to handle it and continue processing, then yes, you should check for it rather than throwing an exception. But if, no matter how expected a special case is, all you can do when it happens is cry panic and let loose the dogs of war, then just throw an exception. – Jay Feb 14 '10 at 01:12
  • But mega dittos on #3 and #4. Catching a generic exception is rarely productive. You have no idea what you're catching. By the way, I might add: Corollary: Don't throw generic exceptions. If your program detects an error condition and you want to throw an exception, take the ten minutes to create a new class for it that extends exception. Don't just 'throw new Exception("Foo was missing a bar")' or whatever. – Jay Feb 14 '10 at 01:14
3

The answer lies in your program's own output - it prints "Infinity" for result. This is because Java only disallows integer division by zero - floating point division by zero is legal and produces Infinity.

See the documentation of Double and Float for the POSITIVE_INFINITY and NEGATIVE_INFINITY constants.

danben
  • 80,905
  • 18
  • 123
  • 145
2

Only division by zero with integers will raise an ArithmeticException. Division by zero with double or float will result in Infinity.

Desintegr
  • 6,992
  • 1
  • 22
  • 17
1

Because dividing two doubles returns a Infinity, but doesn't throw. You can use isInfinite() to check for this. However, the appropriate solution (as already noted) is to check the denominator before the division.

Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
  • dividing only returns a NaN if one of the arguments is NaN or both are infinity or both are zero. Dividing a nonzero by zero - the question - results in positive or negative Infinity. http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.17.2 – user85421 Feb 13 '10 at 23:43
0

No one should try to expect RuntimeException to be thrown from their code. These Exceptions can be (and should be) avoided easily.

fastcodejava
  • 39,895
  • 28
  • 133
  • 186