首先問一下round(0.825,2) 返回的結果,大家猜一猜,
首先SQL server 返回的是 0.83
js的返回結果 是0.83,code 如下:
var b = 0.825; alert(Math.round(b * 100) / 100); 其實js中可以 直接用toFixed函數的,
var b = 0.825; alert(b.toFixed(2));
這樣也返回0.83
可是C# 返回的是0.82
這里並不是我們期望的0.83, 為什么了? 其實C#中的Math.Round()並不是使用的"四舍五入"法 而是四舍六入五取偶(銀行家算法 Banker's rounding),若需要舍入到的位的后面"小於5"或"大於5"的話,按通常意義的四舍五入處理.若"若需要舍入到的位的后面"等於5",則要看舍入后末位為偶數還是奇數.
Math.Round(1.25, 1) = 1.2 因為5前面是2,為偶數,所以把5舍去不進位 Math.Round(1.35, 1) = 1.4 因為5前面是3,為奇數,所以進位.
為了解決這個 問題,微軟提供了其他的API
Round(Decimal, MidpointRounding)
Round(Double, MidpointRounding)
Round(Decimal, Int32, MidpointRounding)
Round(Double, Int32, MidpointRounding)
網上有人說 這個API 計算小數時有問題, 其實我們可以自己實現Round 函數,
public static decimal Round(decimal d, int decimals) { decimal tenPow = Convert.ToDecimal(Math.Pow(10, decimals)); decimal scrD = d * tenPow + 0.5m; return (Convert.ToDecimal(Math.Floor(Convert.ToDouble(scrD))) / tenPow); }
或者如下,
public static decimal Round(decimal d, int decimals) { d = d + 0.000000000000001m; return Decimal.Round(d, decimals); }
如果我們現在需要 用js 來實現 銀行家算法,又該怎么實現了
Number.prototype.round = function (len) { var old = this; var a1 = Math.pow(10, len) * old; a1 = Math.round(a1); var oldstr = old.toString() var start = oldstr.indexOf("."); if (start > 0 && oldstr.split(".")[1].length == len + 1) { if (oldstr.substr(start + len + 1, 1) == 5) { var flagval = oldstr.substr(start + len, 1) - 0; if (flagval % 2 == 0) { a1 = a1 - 1; } } } var b1 = a1 / Math.pow(10, len); return b1; } Number.prototype.oldtoFixed = Number.prototype.toFixed; Number.prototype.toFixed = function (len) { var old = this; var oldstr = old.toString() var start = oldstr.indexOf("."); if (len == 2 && start > 0 && oldstr.split(".")[1].length == 3) { return this.round(len); } else { return this.oldtoFixed(len); } }