You can compare it with Long.MIN_VALUE and Long.MAX_VALUE :
public static boolean fitsLong(double d) { return d >= Long.MIN_VALUE && d < Long.MAX_VALUE; }
A slightly more complex approach is to use BigDecimal :
double value = 1234567.9; long l = BigDecimal.valueOf(value) .setScale(0, RoundingMode.HALF_EVEN) .longValueExact();
This way you can control how rounding is done.
You may ask why strict inequality exists in fitsLong : d < Long.MAX_VALUE . In fact, this is because Long.MAX_VALUE itself cannot be represented as a double number. When you create (double)Long.MAX_VALUE , double does not have enough accuracy to represent it, so the closest represented value is selected, which is 9223372036854775808.0 ( Long_MAX_VALUE+1.0 ). Thus, he d <= Long.MAX_VALUE would return true for a number that is actually a little larger, since in this comparison the constant Long.MAX_VALUE raised to a double type. On the other hand, Long.MIN_VALUE can be exactly represented as a double , so here we have >= .
It is also interesting why the following works:
double value = -9223372036854775809.9;
This is because you have not actually read anything from Long.MIN_VALUE . Cm:
double d1 = Long.MIN_VALUE; double d2 = -9223372036854775809.9; System.out.println(d1 == d2);
Double precision is not enough to distinguish between -9223372036854775808 and -9223372036854775809.9 , so this is actually a double number. At compile time, it is converted to binary form, and the binary form is the same for these two numbers. Thus, by compiling the program, you cannot tell if -9223372036854775808 or -9223372036854775809.9 in the source code.
If you feel that there is still a problem, build BigDecimal from String :
long l = new BigDecimal("-9223372036854775808.2") .setScale(0, RoundingMode.HALF_EVEN) .longValueExact(); // ok, -9223372036854775808 long l = new BigDecimal("-9223372036854775808.9") .setScale(0, RoundingMode.HALF_EVEN) .longValueExact(); // ArithmeticException