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 Alert
- Compare with Intl.NumberFormat
- Wrap Up
- Polyfill
Bug Reports
There is a long history of bug reports with respect to rounding errors using toFixed()
.
- Chrome
- Firefox
- Firefox, see also
- Internet Explorer
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%