指定精度的四舍五入问题,一直都比较麻烦,没有一个万能的统一的处理,如:
1、Math.round() 函数,它的算法为Math.floor(x+0.5) ,floor 返回不大于的最大整数,求指定精度时:(Math.round(a_Num * Math.pow(10,a_Bit)) /Math.pow(10,a_Bit)) 所以
Round(516889.3*370.55,2) = 191533330.12
Round(-516889.3*370.55,2) = -191533330.11
516889.3*370.55 = 191533330.115;
Math.round(19153333011.5) = 19153333012 ;
//19153333011.5 + 0.5 = 19153333012,floor(19153333012)= 19153333012
Math.round(-19153333011.5) = -19153333011 ;
//-19153333011.5 + 0.5 = -19153333011 ,
floor(-19153333011)= 19153333011
从而导致 A*B !=-(-A*B) 现象。
2、NumberObject.toFixed(num),定义和用法: toFixed() 方法可把 Number 四舍五入为指定小数位数的数字。
经过测试 NumberObject.toFixed(num),则为:
new Number(191533330.115).toFixed(2) = "191533330.12"
new Number(-191533330.115).toFixed(2) = "-191533330.12"
toFixed大部分能支持,但也不是完全支持,比如:new Number(0.009).toFixed(2) = "0.00" ,0.0056.toFixed(2) = "0.00"
一般就是上面两种实现了,但出现那种某几个数的问题时,我们一时也没有想清楚为什么这样,可能跟计算机的二进制存储有关系,如8.655 * 100 != 865.5 而是865.4999999999999。
其实在我们看来,指定精度的四舍五入也没这么麻烦,就是两点:
1、当指定精度a_Bit大于数字本身的精度o_Bit,我们直接返回,后面补够0
2、当a_Bit < o_Bit 时,我们就要截取了,就看指定精度后一位是否大于等于5,是的话就进位
下面就是用这种思路写的一个,算法比较简单,性能可能不太好,但保正确,
注:这里没有处理补0的操作。
1、Math.round() 函数,它的算法为Math.floor(x+0.5) ,floor 返回不大于的最大整数,求指定精度时:(Math.round(a_Num * Math.pow(10,a_Bit)) /Math.pow(10,a_Bit)) 所以
Round(516889.3*370.55,2) = 191533330.12
Round(-516889.3*370.55,2) = -191533330.11
516889.3*370.55 = 191533330.115;
Math.round(19153333011.5) = 19153333012 ;
//19153333011.5 + 0.5 = 19153333012,floor(19153333012)= 19153333012
Math.round(-19153333011.5) = -19153333011 ;
//-19153333011.5 + 0.5 = -19153333011 ,
floor(-19153333011)= 19153333011
从而导致 A*B !=-(-A*B) 现象。
2、NumberObject.toFixed(num),定义和用法: toFixed() 方法可把 Number 四舍五入为指定小数位数的数字。
经过测试 NumberObject.toFixed(num),则为:
new Number(191533330.115).toFixed(2) = "191533330.12"
new Number(-191533330.115).toFixed(2) = "-191533330.12"
toFixed大部分能支持,但也不是完全支持,比如:new Number(0.009).toFixed(2) = "0.00" ,0.0056.toFixed(2) = "0.00"
一般就是上面两种实现了,但出现那种某几个数的问题时,我们一时也没有想清楚为什么这样,可能跟计算机的二进制存储有关系,如8.655 * 100 != 865.5 而是865.4999999999999。
其实在我们看来,指定精度的四舍五入也没这么麻烦,就是两点:
1、当指定精度a_Bit大于数字本身的精度o_Bit,我们直接返回,后面补够0
2、当a_Bit < o_Bit 时,我们就要截取了,就看指定精度后一位是否大于等于5,是的话就进位
下面就是用这种思路写的一个,算法比较简单,性能可能不太好,但保正确,
注:这里没有处理补0的操作。
/**
* 指定精度的四舍五入函数
* @param a_Num
* @param a_Bit
* @return
*/
function Round(a_Num,a_Bit){
a_Bit = parseInt(a_Bit)
var tempNum = 0,isNegative = a_Num < 0;
var thisStr = a_Num + "";
var start = thisStr.indexOf(".");
//获取旧的精度,如果没有精度或小于要转化的精度,则直接返回原值
var oldScale = thisStr.length - start - 1;
if (start == -1 || oldScale <= a_Bit) {
return a_Num;
}
//截取小数点后,scale之后的数字,判断是否大于5,如果大于5这入为1
if(thisStr.substr(start + a_Bit + 1,1) >= 5) {
tempNum = 1;
}
//计算10的scale次方,把原数字扩大它要保留的小数位数的倍数
var temp = Math.pow(10,a_Bit);
//截取指定长度的数字,加上进位
var s = Math.abs(thisStr.substring(0,start+a_Bit+1).replace('.','')) + tempNum;
var result = s/temp;
if (isNegative) {
result = -result;
}
return result;
}
function test(){
var a = Round(191533330.115,2);//191533330.12
var b = Round(-191533330.115,2);//-191533330.12
var c = Round(19153333011,2);//19153333011
var d = Round(8.655,2);//8.66
var e = Round(0.009,2);//0.01
var g = Round(19153333011.995,2);//19153333012
}