Variable precision in d3.format

d3.js, format, javascript, svg

Solution

While 1400 * .001 is 1.4000000000000001, 1400 / 1000 is 1.4; multiplying an integer by a negative power of ten (such as .001) may introduce rounding error, but it appears that dividing an integer by a power of ten (such as 1000) does not. Or at least, it's less likely? I've implemented a tentative fix in the fix-si-format-rounding branch. It's strictly backwards-incompatible, but since the `d3.formatPrefix` function is undocumented, I think it'd be safe to include in the next patch release.

Edit: This fix was released in version 2.9.2.

Problem

I'm using d3.format("s") with d3.svg.axis.tickFormat to nicely format the tick labels with SI units (from the International System of Units). It works beautifully for the most part, except for certain values that run into a rounding error and return a ton of decimal places (1400, for example, as 1400 * 0.001 = 1.4000000000000001). To get around this I can specify a precision, such as d3.format(".2s") but this forces 2 significant digits in cases where 1 would be better. For example, if I have ticks [5000, 10000, 15000] I would now see [5.0k, 10k, 15k]. Originally when I didn't specify precision at all I got [5k, 10k, 15k]. I'm wondering if it's possible to specify a maximum precision such that it will only get applied when the number of significant digits exceeds the number specified? So 5000 would be 5k and not 5.0k.

Original source