Consider this code:
double d = 9000000000000000000d;
while (d == 9000000000000000000d)
d += 500;
A double has a varying precision, i.e. a fixed number of significant bits.
A double/float number (floating point number) consists of an exponent and a mantisse (cf. the IEEE754 standard). The logic bebind this is that with larger numbers one doesn't need a high precision for small numbers, whereas for small numbers one needs a high precision. So, it might happen that
d==d+1 is true as
+1 does nothing for large numbers (That's also a reason why one should not use floating point numbers for representing money; also comparing floating point numbers is problematic as
4*0.1!=0.4 might be true, depending on the implementation and possible rounding errors). This is defined in the IEEE754 standard and, thus, won't throw any exception (btw. compilers can issue warning or errors, but don't throw any exceptions).
That's in contrast to integers which always have a precision of
1. So, if you need to handle large numbers with a precision of 1, you need to consider to use BigInteger implementations or use
decimal with a fixed set of decimal digits and guaranteed precision.