DEV Community

CertosinoLab
CertosinoLab

Posted on

JavaScript Finally Fixed Summation — But 0.1 + 0.2 Is Still Broken

Comparison between ordinary JavaScript summation and Math.sumPrecise showing intermediate floating-point precision loss

If you've written JavaScript for more than five minutes, you've probably seen this:

0.1 + 0.2
// 0.30000000000000004
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Wait.

Mathematically:

100000000000000000000
+                  0.1
-100000000000000000000
--------------------------------
                   0.1
Enter fullscreen mode Exit fullscreen mode

The answer should be 0.1.

JavaScript gives us:

0
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

That's it.

No library.

No custom summation algorithm.

No special class.

Just:

Math.sumPrecise(iterable);
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

is effectively stored as:

1e20
Enter fullscreen mode Exit fullscreen mode

The 0.1 has disappeared.

Then our reduction continues:

1e20 + -1e20
Enter fullscreen mode Exit fullscreen mode

which gives:

0
Enter fullscreen mode Exit fullscreen mode

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
    ↓
...
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
]);
Enter fullscreen mode Exit fullscreen mode

The result is:

0.30000000000000004
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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...
Enter fullscreen mode Exit fullscreen mode

certain decimal fractions cannot be represented exactly as finite binary fractions.

So when you write:

0.1
Enter fullscreen mode Exit fullscreen mode

the value stored by JavaScript is already the closest representable floating-point approximation.

The same happens with:

0.2
Enter fullscreen mode Exit fullscreen mode

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])
Enter fullscreen mode Exit fullscreen mode

still produces:

0.30000000000000004
Enter fullscreen mode Exit fullscreen mode

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,
  // ...
];
Enter fullscreen mode Exit fullscreen mode

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
));
Enter fullscreen mode Exit fullscreen mode

Or perhaps you're processing a generator:

function* measurements() {
  yield 1e20;
  yield 0.1;
  yield -1e20;
}

Math.sumPrecise(measurements());
// 0.1
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

And:

Math.sumPrecise(
  new Float64Array([
    10,
    20,
    30
  ])
);

// 60
Enter fullscreen mode Exit fullscreen mode

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
);
Enter fullscreen mode Exit fullscreen mode

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
);
Enter fullscreen mode Exit fullscreen mode

you can express your intention directly:

const total = Math.sumPrecise(values);
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Then convert for display:

const totalInDollars =
  totalInCents / 100;
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Yes, JavaScript has both 0 and -0.

You can verify it with:

Object.is(
  Math.sumPrecise([]),
  -0
);

// true
Enter fullscreen mode Exit fullscreen mode

Also, Math.sumPrecise() expects numbers.

This doesn't work:

Math.sumPrecise([
  1,
  "2",
  3
]);
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

is still:

0.30000000000000004
Enter fullscreen mode Exit fullscreen mode

That's not going anywhere.

But this:

[
  1e20,
  0.1,
  -1e20
].reduce((a, b) => a + b, 0);
Enter fullscreen mode Exit fullscreen mode

returning:

0
Enter fullscreen mode Exit fullscreen mode

no longer has to be the best JavaScript can do.

We can now write:

Math.sumPrecise([
  1e20,
  0.1,
  -1e20
]);

// 0.1
Enter fullscreen mode Exit fullscreen mode

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)