高斯/银行家在JavaScript中四舍五入

我一直在C#中使用Math.Round(myNumber, MidpointRounding.ToEven)来做我的服务器端舍入,但是,用户需要知道'活'的服务器端操作的结果是什么意思(避免Ajax请求)创build一个JavaScript方法来复制C#使用的MidpointRounding.ToEven方法。

MidpointRounding.ToEven是高斯/ 银行的四舍五入 , 这里描述的会计系统的一个非常常见的四舍五入方法。

有人对这个有经验么? 我已经在网上find了一些例子,但是他们并没有达到给定的小数位数。

 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 

现场演示: http : //jsfiddle.net/NbvBp/

对于看起来更严格的处理(我从来没有使用过),你可以试试这个BigNumber实现。

被接受的答案围绕着给定数量的地方。 在这个过程中,它调用toFixed将数字转换为一个string。 由于这是昂贵的,我提供下面的解决scheme。 它将以0.5结尾的数字舍入到最接近的偶数。 它不处理四舍五入到任意数量的地方。

 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); }; 

这是@ soegaard的一个很好的解决scheme。 这是一个小小的变化,使其工作小数点:

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

而在这一点上 – 这里有一些testing:

 console.log(" 1.5 -> 2 : ", bankers_round(1.5) ); console.log(" 2.5 -> 2 : ", bankers_round(2.5) ); console.log(" 1.535 -> 1.54 : ", bankers_round(1.535, 2) ); console.log(" 1.525 -> 1.52 : ", bankers_round(1.525, 2) ); console.log(" 0.5 -> 0 : ", bankers_round(0.5) ); console.log(" 1.5 -> 2 : ", bankers_round(1.5) ); console.log(" 0.4 -> 0 : ", bankers_round(0.4) ); console.log(" 0.6 -> 1 : ", bankers_round(0.6) ); console.log(" 1.4 -> 1 : ", bankers_round(1.4) ); console.log(" 1.6 -> 2 : ", bankers_round(1.6) ); console.log(" 23.5 -> 24 : ", bankers_round(23.5) ); console.log(" 24.5 -> 24 : ", bankers_round(24.5) ); console.log(" -23.5 -> -24 : ", bankers_round(-23.5) ); console.log(" -24.5 -> -24 : ", bankers_round(-24.5) );