指定精度的四舍五入有关问题
指定精度的四舍五入问题
指定精度的四舍五入问题,一直都比较麻烦,没有一个万能的统一的处理,如:
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 }