# Number formatting functions: What algorithm is used for rounding values ending in 5?

I had a value, 0.2435, that I wanted to format in D3 as a percent, rounded to the tenths place. I was expecting "24.4%" but got "24.3%".

I know there are different rounding methods, but couldn't find mention of the one D3 uses. See below for several examples to illustrate the issue.

``````var fmt = d3.format(",.1%");

console.log(fmt(.2405));
console.log(fmt(.2415));
console.log(fmt(.2425));
console.log(fmt(.2435));
console.log(fmt(.2445));
console.log(fmt(.2455));
console.log(fmt(.2465));
console.log(fmt(.2475));
console.log(fmt(.2485));
console.log(fmt(.2495));``````
``<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.4.1/d3.min.js"></script>``

• Found this for anyone reaching this question: github.com/d3/d3-format/issues/27. – Al R. Mar 11 at 22:43
• The GitHub issue you linked pretty much explains the matter: the rounding "problem" you see is by design. Therefore, your best choice is implementing the double rounding described in the issue itself. – Gerardo Furtado Mar 11 at 23:09

Since this question is explicitly asking about the algorithm used internally by D3, not for a solution to the problem OP is facing (which is complicated, see the comments above), here is the description.

When you do this...

``````var fmt = d3.format(",.1%");
``````

... you are setting a `precision` of `1`. After checking for the passed value...

``````precision = precision == null ? 6
: /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
: Math.max(0, Math.min(20, precision));
``````

...this precision will be used here:

``````value = formatType(Math.abs(value), precision);
``````

If we have a look at the source code for `formatType` with `%` as the type, we'll see:

``````"%": function(x, p) { return (x * 100).toFixed(p); },
``````

Where `p` is the precision. Therefore, in your case, this is equivalent to:

``````function(x){
return (x * 100).toFixed(1);
};
``````

And that's the algorithm you're asking.

As a proof, let's see your examples with that algorithm:

``````var d3fmt = d3.format(",.1%");

function jsfmt(x) {
return (x * 100).toFixed(1) + "%";
}

console.log("d3: " + d3fmt(.2405) + " --- pure JS: " + jsfmt(.2405));
console.log("d3: " + d3fmt(.2415) + " --- pure JS: " + jsfmt(.2415));
console.log("d3: " + d3fmt(.2425) + " --- pure JS: " + jsfmt(.2425));
console.log("d3: " + d3fmt(.2435) + " --- pure JS: " + jsfmt(.2435));
console.log("d3: " + d3fmt(.2445) + " --- pure JS: " + jsfmt(.2445));
console.log("d3: " + d3fmt(.2455) + " --- pure JS: " + jsfmt(.2455));
console.log("d3: " + d3fmt(.2465) + " --- pure JS: " + jsfmt(.2465));
console.log("d3: " + d3fmt(.2475) + " --- pure JS: " + jsfmt(.2475));
console.log("d3: " + d3fmt(.2485) + " --- pure JS: " + jsfmt(.2485));
console.log("d3: " + d3fmt(.2495) + " --- pure JS: " + jsfmt(.2495));``````
``<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>``

You can see that they are the same values that you have in your snippet.