Gaussian/banker's rounding in JavaScript

Jimbo picture Jimbo · Jun 24, 2010 · Viewed 10.3k times · Source

I have been using Math.Round(myNumber, MidpointRounding.ToEven) in C# to do my server-side rounding, however, the user needs to know 'live' what the result of the server-side operation will be which means (avoiding an Ajax request) creating a JavaScript method to replicate the MidpointRounding.ToEven method used by C#.

MidpointRounding.ToEven is Gaussian/banker's rounding, a very common rounding method for accounting systems described here.

Does anyone have any experience with this? I have found examples online, but they do not round to a given number of decimal places...

Answer

Tim Down picture Tim Down · Jun 24, 2010
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) ); // 2
console.log( evenRound(2.5) ); // 2
console.log( evenRound(1.535, 2) ); // 1.54
console.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.