Number().toFixed() Rounding Errors: Broken But Fixable

This article was originally published on David Kaye.

I found a rounding bug in Number().toFixed() in every JavaScript environment I’ve tried (Chrome, Firefox, Internet Explorer, Brave, and Node.js). The fix is surprisingly simple. Read on…

Warm Up

I found this version of the rounding bug in toFixed() while revising a number-formatting function that performs the same kind of thing as Intl.NumberFormat#format().

(1.015).toFixed(2) // returns "1.01" instead of "1.02"

The failing test is on line 42 here. I had missed it until December 2017, and that spurred me to check for other problems.

See my tweets about it:

Bug Reports

There is a long history of bug reports with respect to rounding errors using toFixed().

Here is a short sample of StackOverflow questions about this problem:

In general, these point out a bug for a value, but none reports a range or pattern of values returning erroneous results (at least none that I have found, I may have missed something). That leaves the programmers to focus on the small without seeing a larger pattern. I don’t blame them for that.

Finding the Pattern

Unexpected results based on input must arise from a shared pattern in the input. So, rather than review the specification for Number().toFixed(), I focused on testing with a series of values to determine where the bug shows up in each series.

Test Function

I created the following test function to exercise toFixed() over a series of integers ranging from 1 to a maxValue, adding the fraction such as .005 to each integer. The fixed (number of digits) argument to toFixed() is calculated from the length of the fraction value.

Continue reading %Number().toFixed() Rounding Errors: Broken But Fixable%

You may also like...