双鱼座的天蝎

导航

数字取整或保留小数四舍五入的正确写法

【JS篇】

使用toFixed是错误的!请看下面例子:

(0.05).toFixed(1)    //0.1
(0.15).toFixed(1)    //0.1
(0.25).toFixed(1)    //0.3
(0.35).toFixed(1)    //0.3
(0.45).toFixed(1)    //0.5
(0.55).toFixed(1)    //0.6
(0.65).toFixed(1)    //0.7
(0.75).toFixed(1)    //0.8
(0.85).toFixed(1)    //0.8
(0.95).toFixed(1)    //0.9

 

与C#不同的是,js中的Math.round是可以正确显示四舍五入的整数

Math.round(0.5)    //1
Math.round(1.5)    //2
Math.round(2.5)    //3
Math.round(3.5)    //4
Math.round(4.5)    //5
Math.round(5.5)    //6
Math.round(6.5)    //7
Math.round(7.5)    //8
Math.round(8.5)    //9
Math.round(9.5)    //10

 

所以在js中,正确的四舍五入应该这样写:

Math.round(0.05 * 10) / 10    //0.1
Math.round(0.15 * 10) / 10    //0.2
Math.round(0.25 * 10) / 10    //0.3
Math.round(0.35 * 10) / 10    //0.4
Math.round(0.45 * 10) / 10    //0.5
Math.round(0.55 * 10) / 10    //0.6
Math.round(0.65 * 10) / 10    //0.7
Math.round(0.75 * 10) / 10    //0.8
Math.round(0.85 * 10) / 10    //0.9
Math.round(0.95 * 10) / 10    //1

 

如果需要强制保留小数位数,再加上toFixed就可以了

(Math.round(0.95 * 10) / 10).toFixed(1)    //1.0

 

为了方便使用,封装一下:

//小数四舍五入,f精度范围[0,10]
Number.prototype.numberRound = function (f) {
    return NumberRound(this, f);
}
String.prototype.numberRound = function (f) {
    return NumberRound(this, f);
}
function NumberRound(n, f) {
    n = parseFloat(n);
    f = (f == "" || isNaN(f)) ? 0 : (f > 10 ? 10 : parseInt(f));var x = Math.pow(10, f);
    return Math.round(n * x) / x;
}

 

所以,这样用起来就更方便了:

(0.15).numberRound(1)        //0.2
"0.15".numberRound(1)        //0.2
"0.15".numberRound("")       //0      空,精度为0
"0.15".numberRound("abc")    //0      非数字,精度为0
"0.15".numberRound(10000)    //0.15   超出精度最大值,精度为10
    

 

如果非要保留位数,就再加一个toFixed就可以了

(0.095).numberRound(1).toFixed(2)    //0.10

 

【C#篇】

相比JS,疑似C#四舍五入的方法有很多,最广泛使用的Convert.ToInt32是错误的!请看下面例子:

Convert.ToInt32(0.5)    //0
Convert.ToInt32(1.5)    //2
Convert.ToInt32(2.5)    //2
Convert.ToInt32(3.5)    //4
Convert.ToInt32(4.5)    //5
Convert.ToInt32(5.5)    //6
Convert.ToInt32(6.5)    //6
Convert.ToInt32(7.5)    //8
Convert.ToInt32(8.5)    //8
Convert.ToInt32(9.5)    //10

 

那么,我们熟悉的Math.Round呢?竟然结果和上面完全一样!也是错误的。

但是,Math.Round后面有一个可选参数(MidpointRounding.AwayFromZero),加上以后就正确了:

Math.Round(0.5,MidpointRounding.AwayFromZero)    //1
Math.Round(1.5,MidpointRounding.AwayFromZero)    //2
Math.Round(2.5,MidpointRounding.AwayFromZero)    //3
Math.Round(3.5,MidpointRounding.AwayFromZero)    //4
Math.Round(4.5,MidpointRounding.AwayFromZero)    //5
Math.Round(5.5,MidpointRounding.AwayFromZero)    //6
Math.Round(6.5,MidpointRounding.AwayFromZero)    //7
Math.Round(7.5,MidpointRounding.AwayFromZero)    //8
Math.Round(8.5,MidpointRounding.AwayFromZero)    //9
Math.Round(9.5,MidpointRounding.AwayFromZero)    //10

 

然后,再用ToString()试试:

(0.05).ToString("0.0")    //0.1
(0.15).ToString("0.0")    //0.2
(0.25).ToString("0.0")    //0.3
(0.35).ToString("0.0")    //0.4
(0.45).ToString("0.0")    //0.5
(0.55).ToString("0.0")    //0.6
(0.65).ToString("0.0")    //0.7
(0.75).ToString("0.0")    //0.8
(0.85).ToString("0.0")    //0.9
(0.95).ToString("0.0")    //1.0

 

很好,接着试ToString("#0.0")ToString("f1")ToString("g1"),也是一样的结果,都是正确的!

 

ToString("#0.0")ToString("0.0")是一样的,但ToString("0.0")ToString("0.#")不一样:前者保留多余的0,后者省略多余的0

f1表示精度为1位,自动补0;g1表示精度为1位,不会补0,所以在C#中,四舍五入其实很简单,直接 ToString()就可以了:

(0.65).ToString("f1")        //0.7
(0.65).ToString("f3")        //0.650
(0.65).ToString("g3")        //0.65

 

posted on 2017-09-07 16:06  双鱼座的天蝎  阅读(3273)  评论(0编辑  收藏  举报