13

How to force Java to throw arithmetic exception on dividing by 0.0 or extracting root from negative double? Code follows:

   double a = 1; // or a = 0 to test division by 0
   double b = 2;
   double c = 100;

   double d = b*b - 4*a*c;
   double x1 = (-b - Math.sqrt(d)) / 2 / a;
   double x2 = (-b + Math.sqrt(d)) / 2 / a;
DNNX
  • 6,215
  • 2
  • 27
  • 33
  • Isn't the quadratic formula supposed to be divided by 2*a and not 2/a ? –  Feb 17 '10 at 14:14
  • **Why** do you want to get an exception instead of just checking the outcome? Or was the *actual* problem that you don't know how to check the outcome? – BalusC Feb 17 '10 at 14:17
  • 1
    @DyingCactus: x/2/a == x/(2*a) – Tom R Feb 17 '10 at 14:21
  • DyingCactus, the thing I wrote ((-b - Math.sqrt(d)) / 2 / a) is the same as (-b - Math.sqrt(d)) / (2 * a) – DNNX Feb 17 '10 at 14:24
  • 1
    I asked a similar question here: http://stackoverflow.com/questions/2140501/java-maths-testing-for-nan – Pool Feb 17 '10 at 14:39
  • 2
    @BalusC Likely because the exception could have more information about where and how the problem occurred than just "something went wrong here". The underlying hardware very likely has support for trapping these conditions right at the FPU instruction where the NaN appears, but Java does not expose this mechanism. – Jouni K. Seppänen Mar 13 '11 at 19:43

3 Answers3

14

It's not possible to make Java throw exceptions for these operations. Java implements the IEEE 754 standard for floating point arithmetic, which mandates that these operations should return specific bit patterns with the meaning "Not a Number" or "Infinity". Unfortunately, Java does not implement the user-accessible status flags or trap handlers that the standard describes for invalid operations.

If you want to treat these cases specially, you can compare the results with the corresponding constants like Double.POSITIVE_INFINITY (for NaN you have to use the isNAN() method because NaN != NaN). Note that you do not have to check after each individual operation since subsequent operations will keep the NaN or Infinity value. Just check the end result.

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
  • 1
    just a note: `Double.NaN != Double.NaN` is **true** and `Double.NaN == Double.NaN` is **false**, better use `Double.isNaN(double)` – user85421 Feb 17 '10 at 15:16
  • 8
    It's not true that Java's lack of floating-point exceptions is *because* it implements IEEE 754. The Java virtual machine specifically *[differs](http://java.sun.com/docs/books/jvms/second_edition/html/Overview.doc.html#35254)* from IEEE 754 by not having any way to trap or flag these conditions. – Jouni K. Seppänen Mar 13 '11 at 19:37
  • Fix this answer in light of Jouni's comment, please – Aleksandr Dubinsky Sep 01 '19 at 01:03
  • @AleksandrDubinsky Done. Unfortunately, the link to the JVMS is broken, and I couldn't find where it supposedly says it differs from the spec, so I had to rely on a rather superficial description of the spec behaviour from Wikipedia. – Michael Borgwardt Sep 01 '19 at 20:16
  • The Java spec doesn't actually mention traps, but traps (equivalent to Java exceptions) have existed in the IEEE 754 standard since 1985. (That's _before_ Java.) I'm curious why Java doesn't expose them. Interestingly, C# doesn't expose enabling traps either, but will catch them if they're on! https://stackoverflow.com/a/17859645/1151521 Might it work for Java? There is another way that Java differs from IEEE 754. The standard annoyingly doesn't propagate NaNs through min and max, but Java does. (This has been addressed in the 2019 update to IEEE 754, after merely 34 years.) – Aleksandr Dubinsky Sep 02 '19 at 20:18
  • @AleksandrDubinsky: I suspect that traps were omitted for reasons of platform independance since the standard merely suggests them as a feature. – Michael Borgwardt Sep 02 '19 at 21:07
4

I think, you'll have to check manually, e.g.

public double void checkValue(double val) throws ArithmeticException {
    if (Double.isInfinite(val) || Double.isNaN(val))
        throw new ArithmeticException("illegal double value: " + val);
    else
        return val;
}

So for your example

double d = checkValue(b*b - 4*a*c);
double x1 = checkValue((-b - Math.sqrt(d)) / 2 / a);
double x2 = checkValue((-b + Math.sqrt(d)) / 2 / a);
sfussenegger
  • 35,575
  • 15
  • 95
  • 119
  • 1
    I don't want to call checkValue every time when division by zero or another "bad" operation may occur. I'd like to surround my code with try-catch and check for failures in one code block, having housekeeping stuff (i.e checkValue() calls) out of the main code. – DNNX Feb 17 '10 at 14:27
  • @DNNX: the "check in one place" method is supported by `NaN`: When a problem occurs then the end result of your calculation will be `NaN`. Just check for that in the end. – Joachim Sauer Feb 17 '10 at 14:38
  • @DNNX "You can't always get what you want / But if you try sometime, you'll find / You get what you need" (Jagger/Richards) ;) – sfussenegger Feb 17 '10 at 15:13
-1

This code will throw an ArithmeticException:

int x = 1 / 0;
Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614