d3-format icon indicating copy to clipboard operation
d3-format copied to clipboard

formatPrefix will sometimes not perform rounding

Open jdharrisnz opened this issue 3 years ago • 5 comments

For example: d3.formatPrefix(',.2', 1e3)(1555) produces 1.55, should be 1.56.

This is likely a simple fix, but unfortunately I'm not adept enough to figure out the source code and submit a PR, sorry.

jdharrisnz avatar Oct 06 '22 10:10 jdharrisnz

This appears to be a problem with Chrome's .toFixed() function, where numbers ending in 5 won't round up. The workaround is to use Math.round() before calling .toFixed().

This seems to require an update to the f type in formatTypes.js.

So for the above case it would be: (Math.round(1.555*100)/100).toFixed(2)

And in the generalised sense: "f": (x, p) => (Math.round(x * Number('1e' + i)) / Number('1e' + i)).toFixed(p)

jdharrisnz avatar Oct 06 '22 10:10 jdharrisnz

I'm seeing the same behavior with Firefox and Safari. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed, which has a detailed explanation (for 2.55).

Fil avatar Oct 06 '22 10:10 Fil

Working as intended.

mbostock avatar Oct 06 '22 15:10 mbostock

Well, (1.555).toFixed(2) producing "1.55" is the intended behavior. But I guess d3.formatPrefix introducing rounding error is not intended.

mbostock avatar Oct 06 '22 15:10 mbostock

I made a local branch to submit a PR but I don't have write access.

The needed change is to formatTypes.js.

"f": (x, p) => (Math.round(x * Number('1e' + p)) / Number('1e' + p)).toFixed(p);

My earlier comment had i instead of p for some reason, oops.

jdharrisnz avatar Sep 15 '23 21:09 jdharrisnz