Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gaussian/banker's rounding in JavaScript

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...

like image 716
Jimbo Avatar asked Jun 24 '10 10:06

Jimbo


People also ask

What is Banker's rounding?

It's a commonly used method for rounding taxes. Rather than rounding 0.5 and higher up, and 0.4 and lower down, bankers rounding rounds 0.5 to the nearest even number. Essentially if the cent value of the tax total is odd, the 0.5 (half-cent) rounds upwards; If the cent value is even, the half-cent rounds it downwards.

How do you round to 5 in JavaScript?

To round a number to the nearest 5, call the Math. round() function, passing it the number divided by 5 and multiply the result by 5 .

How do I always round down in JavaScript?

The Math. floor() method rounds a number DOWN to the nearest integer.


2 Answers

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.

like image 77
Tim Down Avatar answered Sep 29 '22 19:09

Tim Down


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); } 
like image 29
Adi Fairbank Avatar answered Sep 29 '22 18:09

Adi Fairbank