If you've written JavaScript for more than five minutes, you've probably seen this:
0.1 + 0.2
// 0.30000000000000004
It has become one of those JavaScript jokes we all know.
But in 2026, JavaScript got a new method that sounds like it should finally solve the problem:
Math.sumPrecise()
So... is floating-point pain finally over?
Not exactly.
Math.sumPrecise() solves a real and surprisingly common precision problem, but probably not the one you're thinking about.
And understanding the difference tells us something important about how JavaScript numbers actually work.
The problem with the way we usually sum numbers
Let's say we want to add a list of numbers.
Most JavaScript developers would probably reach for reduce():
const numbers = [10, 20, 30, 40];
const total = numbers.reduce(
(sum, number) => sum + number,
0
);
console.log(total);
// 100
Nothing wrong here.
For ordinary numbers, this works exactly as expected.
But now let's make things more interesting:
const numbers = [
1e20,
0.1,
-1e20
];
const total = numbers.reduce(
(sum, number) => sum + number,
0
);
console.log(total);
// 0
Wait.
Mathematically:
100000000000000000000
+ 0.1
-100000000000000000000
--------------------------------
0.1
The answer should be 0.1.
JavaScript gives us:
0
And this is exactly the kind of problem Math.sumPrecise() was created to address.
Meet Math.sumPrecise()
The same calculation can now be written as:
Math.sumPrecise([
1e20,
0.1,
-1e20
]);
// 0.1
That's it.
No library.
No custom summation algorithm.
No special class.
Just:
Math.sumPrecise(iterable);
The method accepts an iterable of JavaScript numbers and returns their sum while avoiding the precision loss that can happen during intermediate additions.
Math.sumPrecise() was standardized as part of ECMAScript 2026 and became Baseline Newly Available across modern browsers in April 2026.
But to understand why this matters, we need to look at what went wrong with reduce().
Why did reduce() return zero?
JavaScript's regular Number type uses IEEE 754 double-precision floating-point numbers.
That means numbers have a limited amount of precision.
Consider this:
1e20 + 0.1
1e20 is enormous compared with 0.1.
At that magnitude, JavaScript cannot represent the tiny difference introduced by adding 0.1.
So this:
1e20 + 0.1
is effectively stored as:
1e20
The 0.1 has disappeared.
Then our reduction continues:
1e20 + -1e20
which gives:
0
The important part is that the precision was lost during an intermediate calculation.
Once that information is gone, the next addition can't magically recover it.
This is why the order in which floating-point operations happen can sometimes affect the result of a naive summation.
What Math.sumPrecise() does differently
Conceptually, instead of repeatedly doing this:
current sum
+
next number
↓
round
↓
current sum
+
next number
↓
round
↓
...
Math.sumPrecise() performs the summation in a way that preserves the contributions of the input values much more accurately before producing the final JavaScript Number.
MDN describes the behavior roughly as if the exact mathematical values represented by the input floating-point numbers were summed first, with the final result then converted to the nearest representable 64-bit floating-point value.
Compare them:
const values = [
1e20,
0.1,
-1e20
];
values.reduce((a, b) => a + b, 0);
// 0
Math.sumPrecise(values);
// 0.1
Or with integers of dramatically different magnitudes:
const values = [
10_000_000_000_000_000,
1,
-10_000_000_000_000_000
];
values.reduce((a, b) => a + b, 0);
// 0
Math.sumPrecise(values);
// 1
That's a meaningful improvement.
But now comes the interesting part.
Does it fix 0.1 + 0.2?
Let's try it.
Math.sumPrecise([
0.1,
0.2
]);
The result is:
0.30000000000000004
Yep.
Our favorite JavaScript number is still alive.
So what happened?
Math.sumPrecise() can't fix numbers that were already approximate
The famous 0.1 + 0.2 issue is slightly different from our previous example.
The problem begins before the addition even happens.
Numbers such as:
0.1
0.2
cannot be represented exactly using binary floating point.
In the same way that 1 / 3 cannot be represented exactly with a finite number of decimal digits:
0.333333333333...
certain decimal fractions cannot be represented exactly as finite binary fractions.
So when you write:
0.1
the value stored by JavaScript is already the closest representable floating-point approximation.
The same happens with:
0.2
Math.sumPrecise() can accurately add the floating-point values it receives.
But it cannot turn those values back into the exact decimal numbers you originally had in mind.
That's why:
Math.sumPrecise([0.1, 0.2])
still produces:
0.30000000000000004
This distinction is probably the most important thing to understand about the new API.
Math.sumPrecise() fixes precision lost while summing.
It does not fix precision already lost when representing a number.
So when is Math.sumPrecise() actually useful?
Consider a dashboard collecting thousands of measurements.
const measurements = [
1200000000,
0.00021,
0.00017,
-1200000000,
0.00034,
// ...
];
Or scientific data where values can have dramatically different magnitudes.
Or analytics where you're aggregating a large iterable:
const total = Math.sumPrecise(events.map(
event => event.value
));
Or perhaps you're processing a generator:
function* measurements() {
yield 1e20;
yield 0.1;
yield -1e20;
}
Math.sumPrecise(measurements());
// 0.1
Notice that Math.sumPrecise() doesn't require an array.
It accepts an iterable.
That means things such as arrays, sets, typed arrays, and generators can be passed directly when they yield numbers.
For example:
Math.sumPrecise(
new Set([10, 20, 30])
);
// 60
And:
Math.sumPrecise(
new Float64Array([
10,
20,
30
])
);
// 60
That makes the API pleasantly small and composable.
Should we stop using reduce() for sums?
Not necessarily.
This:
numbers.reduce(
(sum, n) => sum + n,
0
);
isn't suddenly bad code.
For many applications, especially when you're adding ordinary integers or values with similar magnitudes, the result will be perfectly fine.
But there is now a more expressive operation when what you actually mean is:
“Give me the most accurate sum of these JavaScript numbers.”
Instead of implementing summation using a generic reduction:
const total = values.reduce(
(total, value) => total + value,
0
);
you can express your intention directly:
const total = Math.sumPrecise(values);
I like APIs like this.
Not because they make JavaScript dramatically more powerful, but because they move a surprisingly subtle problem into the language itself.
One important warning: money
You might see the word precise and immediately think:
Great. I'll use this for prices.
Be careful.
Consider:
Math.sumPrecise([
0.1,
0.2
]);
// 0.30000000000000004
Math.sumPrecise() does not turn JavaScript Numbers into decimal numbers.
If your application requires exact decimal arithmetic — especially financial calculations — the underlying binary floating-point representation is still relevant.
A common approach for currencies is to store values using the smallest unit:
const pricesInCents = [
10,
20,
35
];
const totalInCents =
Math.sumPrecise(pricesInCents);
console.log(totalInCents);
// 65
Then convert for display:
const totalInDollars =
totalInCents / 100;
Depending on the requirements of the application, you may instead need BigInt or a dedicated decimal arithmetic solution.
Math.sumPrecise() makes summation better.
It does not change JavaScript's numeric model.
A couple of surprising edge cases
There are some details worth knowing.
An empty iterable returns negative zero:
Math.sumPrecise([]);
// -0
Yes, JavaScript has both 0 and -0.
You can verify it with:
Object.is(
Math.sumPrecise([]),
-0
);
// true
Also, Math.sumPrecise() expects numbers.
This doesn't work:
Math.sumPrecise([
1,
"2",
3
]);
It throws a TypeError instead of coercing "2" into the number 2.
That's actually a nice property.
A function whose purpose is numerical accuracy probably shouldn't silently start converting random strings.
Can I use it today?
As of 2026, yes — with the usual compatibility caveat.
Math.sumPrecise() became Baseline Newly Available in April 2026, meaning current releases of the major browser engines support it, although older browsers and devices may not.
If your application supports older environments, feature detection is simple:
if (typeof Math.sumPrecise === "function") {
const total =
Math.sumPrecise(values);
}
There are also polyfill implementations available through projects such as core-js.
Whether you should ship a fallback depends, as always, on the browsers your users actually run.
reduce() vs Math.sumPrecise()
Here's the mental model I would keep:
reduce((a, b) => a + b) |
Math.sumPrecise() |
|
|---|---|---|
| Simple sums | ✅ | ✅ |
| Works with floating-point numbers | ✅ | ✅ |
| Minimizes intermediate precision loss | ❌ | ✅ |
Fixes 0.1 + 0.2
|
❌ | ❌ |
| Accepts iterables directly | Depends | ✅ |
| Exact decimal arithmetic | ❌ | ❌ |
| Communicates “sum these values” directly | Kind of | ✅ |
The most important row is probably this one:
Fixes 0.1 + 0.2 → NO
Because the name sumPrecise() makes it very easy to assume otherwise.
JavaScript didn't fix floating point. It fixed summation.
And I think that's the right way to think about this feature.
This:
0.1 + 0.2
is still:
0.30000000000000004
That's not going anywhere.
But this:
[
1e20,
0.1,
-1e20
].reduce((a, b) => a + b, 0);
returning:
0
no longer has to be the best JavaScript can do.
We can now write:
Math.sumPrecise([
1e20,
0.1,
-1e20
]);
// 0.1
It's a small API.
Probably not one that will change the way you write JavaScript every day.
But it's also the kind of language improvement I enjoy: taking something deceptively difficult, giving it a clear name, and making the correct solution a one-liner.
So no, JavaScript hasn't finally defeated floating point.
But it did quietly become a lot better at adding numbers.
And honestly, I'll take that.

Top comments (0)