Numeric Literal Loses Precision
ID |
javascript.no_loss_of_precision |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
JavaScript |
Tags |
reliability, suspicious-comparison |
Description
Reports numeric literals that cannot be represented exactly as a JavaScript Number (IEEE 754 double precision) and therefore parse to a different value than the source text shows.
Rationale
Number in JavaScript is a 64-bit double. Integers above 2 ** 53 (Number.MAX_SAFE_INTEGER = 9007199254740991) and decimals with more than ~17 significant digits cannot be stored exactly. The runtime silently rounds the literal to the nearest representable double, which means a literal like 9007199254740993 ends up equal to 9007199254740992 — the visual constant in the source no longer matches the runtime value.
const a = 9007199254740993; // becomes 9007199254740992
const b = 5123000000000000000; // becomes 5.123e18 with low-bit rounding
const c = 0.1234567890123456789; // tail digits silently dropped
Remediation
-
If the value fits in 64-bit but not in a double, use a
BigIntliteral:9007199254740993n. -
If the value must be a regular
Numberand the precision-loss is acceptable, split or compute it at runtime so the source code does not carry a misleading constant.
// Good
const safe = 9007199254740991;
const big = 9007199254740993n;