JS之浮点数精度丢失问题

JS中,在进行浮点数计算的时候,会出现精度丢失的问题,如下:

alert(0.1 + 0.2); 
alert(0.3 - 0.2);
alert(0.1 * 0.2);
alert(0.
3 * 0.2);

正常情况,得出的结果应该是0.3, 0.1, 0.02, 1.5, 但是实际得出的结果却不是这样,如下

可以看到,得出的结果并不是我们预期的结果,造成这样的原因就是浮点数丢失造成的,那么如何解决呢,通过已有的只是可以解决这个问题,如下:

浮点数加法精度丢失解决办法

分析:

   1. 既然是浮点数进行加法运算造成的精度丢失,那么可不可以考虑换算成整数计算,再除以相同小数位呢

    2.  获取小数位的长度,number.tostring().split('.')[1].length

    3. 进行幂运算, Math.pow(10, Math.max(num1, num2))

    4. 对进行算的数进行取整,再除以长度较大的幂次方

程序:

function accAdd(num1, num2){
var r1, r2, m;
try{
r1 = num1.toString().split('.')[1].length; //获取num1的小数位长度
}catch(e){
r1 = 0;
}
try{
r2 = num2.toString().split('.')[1].length;
}catch(e){
r2 = 0;
}
m = Math.pow(10, Math.max(r1, r2)); //取较大的小数位长度进行幂运算

return Math.round(num1*m + num2*m)/m; //将小数位转化成整数,再进行除法

}

  alert(accAdd(0.1, 0.2)); //0.3

这样进行计算后,便可解决精度丢失问题


浮点数减法精度丢失问题

分析:

 减法同加法的类似

  程序:

function accSub(num1, num2){
var r1, r2, m;
try{
r1 = num1.toString().split('.')[1].length; //获取num1的小数位长度
}catch(e){
r1 = 0;
}
try{
r2 = num2.toString().split('.')[1].length;
}catch(e){
r2 = 0;
}
m = Math.pow(10, Math.max(r1, r2)); //取较大的小数位长度进行幂运算
return Math.round(num1*m - num2*m)/m
.toFixed( (r1>= r2) ? r1 : r2 ) ; //将小数位转化成整数,再进行除法
}
  alert(accSub(0.3, 0.2)); //0.1
   

浮点数乘法精度丢失问题

分析:

1.  乘法的情况和加减法不同,因为浮点数相乘的结果,小数位的长度为两浮点数小数位之和,所以方法就不同
2.  获取两个浮点数的小数位长度之和
3. 将两数的转化为字符串去掉小数点,再强转成整数进行计算
程序:

function accMul(num1, num2){
var r1, r2, m = 0, s1 = num1.toString(), s2 = num2.toString();
try{
m += s1.split('.')[1].length; 
}catch(e){}
try{
m += s2.split('.')[1].length; //获取两个数的小数位长度之和
}catch(e){}
//将num1和num2转化为字符串,去掉小数点,再强转成整数进行计算
return Number(s1.replace('.', ''))*Number(s2.replace('.',''))/Math.pow(10, m);
}
  alert(accMul(0.1, 0.2)); //0.02

方法2:

思想类似,使用方法用到之前博客所讲的arguments对象
程序:
         Number.prototype.rate=function(){
             var oStr=this.toString();
             if(oStr.indexOf(".")==-1)//当为真时
                 return 1;
             else
                 return Math.pow(10,parseInt(oStr.length-oStr.indexOf(".")-1));
         }


         function tran(){
             var args=tran.arguments;
             var temp=1;

              /*
              *   当i=0时,args[0]=0.1, args[0].rate()=10
              *   当i=1时,args[1]=0.2, args[1].rate()=10
              * */
             for(var i=0;i<args.length;i++){
                 temp*=args[ i ]*args[ i ].rate();
             }


             for(var i=0;i<args.length;i++) {
                 temp /= args[i].rate();
             }
             return temp;


         }
         alert(tran(0.1, 0.2));    //0.02
 


浮点数除法精度丢失问题:

分析: 和乘法类似
程序:
function accDiv(num1, num2){
var r1, r2, s1 = num1.toString(), s2 = num2.toString();
try{
r1 = s1.split('.')[1].length;
}catch(e){
r1 = 0;
}
try{
r2 = s2.split('.')[1].length;
}catch(e){
r2 = 0;
}

return Number(s1.replace('.',''))/Number(s2.replace('.',''))*Math.pow(10, r2-r1);
}
  alert(accDiv(0.3, 0.2)); //1.5


这就是解决浮点数精度丢失问题的办法,当然还有其他方法,核心思想其实就是转化为整数运算,再除以成小数位。











  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值