Float64 is Java’s double-precision floating-point representation. It provides a wide numeric range, but its representation can surprise code that assumes exact equality, integer-like precision, or integral-type boundary constants. section 4.15.1 section 4.6
Treat these float64 pitfalls explicitly:
- Signed zero: +0.0 and -0.0 compare equal with primitive ==, but boxed Double.equals(), records, hash-based collections, and generated equality can distinguish them. section 4.15.1
- Misleading minimum: Double.MIN_VALUE is the smallest positive double, not the most negative finite value. Use -Double.MAX_VALUE, or consider negative infinity when appropriate. section 4.15.3
- Widening can round: long-to-double loses integer precision at values of at least 2^53, while int-to-float and long-to-float lose precision earlier. section 4.6
- Prefer double over float unless performance justifies float; use BigDecimal when controllable precision matters, and make intentional rounding explicit with a cast. section 4.6
A broken maximum initializer
Initializing a maximum search with Double.MIN_VALUE works only when the input contains a positive value. For an all-negative or zero array, the method can return approximately 4.9 × 10^-324 instead of the actual maximum. Use -Double.MAX_VALUE or an appropriate infinity policy instead. section 4.15.3
long longVal = 1L << 53; double doubleVal = longVal; double doubleValPlusOne = longVal + 1; System.out.println(doubleVal == doubleValPlusOne); #1
Demonstrates two distinct long values becoming equal after conversion to double because binary64 cannot retain every integer beyond 2^53. section 4.6
Set<Double> multiplications = new HashSet<>();
for (double i = -1; i <= 1; i += 0.5) {
for (double j = -1; j <= 1; j += 0.5) {
multiplications.add(i * j);
}
}
System.out.println(multiplications);
Shows a multiplication set retaining both 0.0 and -0.0, making signed-zero behavior visible in a collection. section 4.15.1






