Thursday, 15 March, 2018 UTC


Summary

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:
  • Example one
  • Example two
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%