v147 · JavaScript
Compatibility Lab
Detects Math.sumPrecise availability, runs precision and spec edge cases comparing naive Array.reduce summation against Math.sumPrecise, and provides a Neumaier-compensated fallback that preserves the TypeError, NaN, Infinity, and -0 contracts.
API probes
Precision test battery
Comparing native Math.sumPrecise, a spec-shaped fallback, and naive reduce().
Test results
scenario
expected
reduce()
sumPrecise
contract
Fallback pattern
/* Detect Math.sumPrecise */
const HAS_SUM_PRECISE = typeof Math.sumPrecise === 'function';
/* Spec-shaped fallback: iterable numbers only, -0 for empty/all -0 */
function fallbackSumPrecise(items) {
let state = 'minus-zero';
let sum = 0;
let correction = 0;
for (const n of items) {
if (typeof n !== 'number') throw new TypeError('Math.sumPrecise values must be numbers');
if (Number.isNaN(n)) state = 'not-a-number';
else if (n === Infinity) state = state === 'minus-infinity' ? 'not-a-number' : 'plus-infinity';
else if (n === -Infinity) state = state === 'plus-infinity' ? 'not-a-number' : 'minus-infinity';
else if (!Object.is(n, -0) && (state === 'minus-zero' || state === 'finite')) {
state = 'finite';
const t = sum + n;
correction += Math.abs(sum) >= Math.abs(n) ? (sum - t) + n : (n - t) + sum;
sum = t;
}
}
if (state === 'not-a-number') return NaN;
if (state === 'plus-infinity') return Infinity;
if (state === 'minus-infinity') return -Infinity;
if (state === 'minus-zero') return -0;
return sum + correction;
}
/* Unified API */
function sumPrecise(values) {
if (HAS_SUM_PRECISE) return Math.sumPrecise(values);
return fallbackSumPrecise(values);
}
/* Usage */
const total = sumPrecise([1e20, 0.1, -1e20]);
console.log(total); // 0.1, while reduce() returns 0
references
implementation reference
Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗