A double has finite significand precision, so converting a sufficiently large long can round away its final integer units.
Java long to double: large integer IDs can lose unit precision
Keep identifiers integral
The first integer above 2^53 cannot be represented exactly as a double. The fixture converts 9007199254740993 to double and then back to long; it becomes 9007199254740992. A JSON or analytics pipeline that routes IDs through double can merge two distinct values.
Store identifiers as long, BigInteger, or validated text through boundaries that promise exactness. Exact integer narrowing catches range loss; this page addresses precision loss even though double has a much wider magnitude range.
Separate measurement from identity
Approximate floating-point values can be appropriate for measurements with an error budget. They are a poor intermediate type for ledger sequence numbers, counters that must increment by one, or keys that must round-trip exactly.
Working program
public class LedgerSequencePrecision {
public static void main(String[] args) {
long sequence = 9007199254740993L;
double approximate = sequence;
long roundTrip = (long) approximate;
System.out.println(roundTrip);
System.out.println("same=" + (sequence == roundTrip));
}
}Output
9007199254740992
same=falseCost and ownership
The casts are constant work and storage. The lost unit cannot be restored by casting back; validation must happen before a lossy numeric serialization or transformation.
Common Mistakes
- Do not pass large integer IDs through double-based storage or APIs without an exactness check.
- Do not assume a wide magnitude range implies unit precision.
- Do not use a round-trip cast as a repair after precision was lost.
Read next
Java BigInteger.intValueExact: reject a narrowing conversion, Java floating-point sums: input order can change the result, Java checked integer arithmetic: reject overflow before updating state, Java operators and numeric promotion.
