Gaussian/banker's rounding in JavaScript Gaussian/banker's rounding in JavaScript javascript javascript

Gaussian/banker's rounding in JavaScript


function evenRound(num, decimalPlaces) {    var d = decimalPlaces || 0;    var m = Math.pow(10, d);    var n = +(d ? num * m : num).toFixed(8); // Avoid rounding errors    var i = Math.floor(n), f = n - i;    var e = 1e-8; // Allow for rounding errors in f    var r = (f > 0.5 - e && f < 0.5 + e) ?                ((i % 2 == 0) ? i : i + 1) : Math.round(n);    return d ? r / m : r;}console.log( evenRound(1.5) ); // 2console.log( evenRound(2.5) ); // 2console.log( evenRound(1.535, 2) ); // 1.54console.log( evenRound(1.525, 2) ); // 1.52

Live demo: http://jsfiddle.net/NbvBp/

For what looks like a more rigorous treatment of this (I've never used it), you could try this BigNumber implementation.


This is the unusual stackoverflow where the bottom answers are better than the accepted. Just cleaned up @xims solution and made a bit more legible:

function bankersRound(n, d=2) {    var x = n * Math.pow(10, d);    var r = Math.round(x);    var br = Math.abs(x) % 1 === 0.5 ? (r % 2 === 0 ? r : r-1) : r;    return br / Math.pow(10, d);}


The accepted answer does round to a given number of places. In the process it calls toFixed which converts the number to a string. Since this is expensive, I offer the solution below. It rounds a number ending in 0.5 to the nearest even number. It does not handle rounding to an arbitrary number of places.

function even_p(n){  return (0===(n%2));};function bankers_round(x){    var r = Math.round(x);    return (((((x>0)?x:(-x))%1)===0.5)?((even_p(r))?r:(r-1)):r);};