views:

412

answers:

3

I have code to calculate the percentage difference between 2 numbers - (oldNum - newNum) / oldNum * 100; - where both of the numbers are doubles. I expected to have to add some sort of checking / exception handling in case oldNum is 0. However, when I did a test run with values of 0.0 for both oldNum and newNum, execution continued as if nothing had happened and no error was thrown. Running this code with ints would definitely cause an arithmetic division-by-zero exception. Why does Java ignore it when it comes to doubles?

+11  A: 

The result of division by zero is infinity, which can be expressed with a float/double (as NaN - not a number), but not with an int.

Kris
Exactly. This is defined in the Java Language Spec here: http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.2.3
Michael Myers
I tried outputting the result, and it's an NaN value. Does that mean ints can't hold NaN?
froadie
but this is the case of `0.0/0.0` which is NaN.
Amit Kumar
Infinity is "not a number" in the traditional sense, so it is implemented this way.
Kris
I think there should be an Integer.NaN
OscarRyz
There are mathematical reasons why there isn't Interger.NaN. For example, Elephant and Apple are both not numbers, so each are NaN. But if they were the same NaN they would be equal. But an Elephant != Apple. Now this example doesn't exactly apply when aquiring NaN through numeric means, but the principle is that they end up as separate entities that may or may not be the same.
trinithis
Really? I always thought the result of division by zero is a nonsensical singularity... or "Not A Number".
Software Monkey
@trinithis: your explanation has nothing to do with the reason why there is no Integer.NaN. The reason is simply that the IEEE standard for floating point arithmetic mandates such special values whereas the quasi-standard for integer arithmetic (two's complement) has no such special values, thus leaving it to implementors how to deal with division by zero (raising an interrupt or exception, designating a special value, or just leaving the result undefined).
Michael Borgwardt
@Kris: Strictly speaking it can't be infinity because lim(1/x) is different as x -> 0+ and x -> 0-. But that's a minor quibble.
eaolson
@Oscar Reyes: that would mean there would be an Integer value that did not correspond to a legal int value, which would wreck all sort of havoc, I bet.
eaolson
+3  A: 

The way a double is stored is quite different to an int. See http://firstclassthoughts.co.uk/java/traps/java_double_traps.html for a more detailed explanation on how Java handles double calculations. You should also read up on Floating Point numbers, in particular the concept of Not a Number (NaN).

If you're interested in learning more about floating point representation, I'd advise reading this document (Word format, sorry). It delves into the binary representation of numbers, which may be helpful to your understanding.

Mike
+6  A: 

Java's float and double types, like pretty much any other language out there (and pretty much any hardware FP unit), implement the IEEE 754 standard for floating point math, which mandates division by zero to return a special "infinity" value. Throwing an exception would actually violate that standard.

Integer arithmetic (implemented as two's complement representation by Java and most other languages and hardware) is different and has no special infinity or NaN values, thus throwing exceptions is a useful behaviour there.

Michael Borgwardt