A double stores a sign bit, an 11-bit exponent (biased by 1023) and a 52-bit fraction, the mantissa. 1/10 repeats forever in binary, as 1/3 does in decimal, so 0.1 is stored as the nearest double. Adding the approximations of 0.1 and 0.2 lands one double above the approximation of 0.3, so 0.1 + 0.2 === 0.3 is false.

Math.sumPrecise(iterable) (ES2026) adds numbers as if with exact arithmetic and rounds only the final result, so Math.sumPrecise([1e20, 0.1, -1e20]) is 0.1 where a loop gives 0. It is Baseline 2026 (Chrome 147 1 , Firefox 137 555 , Safari 26.2 10 ) but absent from Node.js 25 2,131 , so feature-detect it. It cannot fix 0.1 + 0.2, because the inputs are already approximations. ES2025 added half precision: Float16Array and Math.f16round() (Baseline 2025, Node.js 24+), which store 16-bit floats for GPU and machine-learning buffers (see Float16Array).
console.log(0.1 + 0.2, [1e20, 0.1, -1e20].reduce((a, b) => a + b));
console.log(Math.sumPrecise?.([1e20, 0.1, -1e20]) ?? "Math.sumPrecise unsupported here");
console.log(Math.f16round(5.05), Math.fround(5.05), new Float16Array([0.1, 65504, 70000]));0.30000000000000004 0 Math.sumPrecise unsupported here 5.05078125 5.050000190734863 Float16Array(3) [ 0.0999755859375, 65504, Infinity ]
Compare floats with a tolerance, round only for display, and compute money in integer cents. The MIT-licensed decimal.js 7,261 (github.com/MikeMcl/decimal.js (https://github.com/MikeMcl/decimal.js 7,261 ), npm 2,036 install decimal.js) stores decimal digits instead of binary fractions: new Decimal(0.3).minus(0.1) is exactly 0.2.