js小数运算精度丢失问题

js小数运算精度丢失问题

问题:

小数的加减法会出现精度丢失,乘除法也会存在精度丢失,示例如下:

var a=0.1;
var b=0.2;
console.log(a+b) //0.30000000000000004
console.log(1.001*1000) //1000.9999999999999

不能直接使用(a*10+b*10)/10了,虽然此案例可以正确显示,但是因为乘法也会精度丢失,有时候也会错误,示例如下:

var a=1.001;
var b=2.002;
console.log((a*1000+b*1000)/1000) //3.0029999999999997
解决方法:
1、思路:

不能使用toFixed方法,因为该方法存在精度丢失问题,示例:

var a=parseFloat(0.1.toFixed(1))
var b=parseFloat(0.2.toFixed(1))
console.log(a+b) //0.30000000000000004

详情可以看我的另一篇文章 toFixed精度不准问题

既然不能使用乘以倍数的方法把小数转化为整数,那么就使用replace方法直接把小数去掉小数点,去掉小数点相当于小数乘以10的n次方,效果相同但方法不同。
然后通过判断小数点后面的小数位数,可以知道每一个小数分别扩大了10的n次方,但是此时两个小数位数不一样,扩大倍数也不一样,那么通过判断哪一个小数点后的位数小,就代表这个数扩大的倍数不够,在他后面补0,补到跟另一个扩大相同的倍数为止,这时两个小数都扩大了相同的倍数,再把这两个字符串parseInt转化为数字,相加,然后除以扩大的倍数。
2、示例(大致过程):
1、假如 a=1,b=0.56     

2、a="1",b="056"  (去掉小数点,转为字符串,此时a没有扩大,但是b扩大了100倍) 

3、a="100"(在a后面补0,扩大相同倍数)

4、a=100,b=56(字符串转为数字)

5、(a+b)/100=1.56
3、代码如下:

假如num1=1,num2=0.2代入计算,方便理解:

function add(num1,num2){
  //将数字转化为字符串
  a=num1.toString();      //a="1"
  b=num2.toString();      //b="0.2"
  //获取小数点的位置
  var index1=a.indexOf(".");    //index1=-1(不存在小数点为-1)
  var index2=b.indexOf(".");    //index2=1
  //如果小数点存在,那么就再获取各自的小数位数
  var ws1=0;        //ws1=0
  var ws2=0;        //ws2=0
  if(index1 !=-1){
    ws1=a.split(".")[1].length;
  }
  if(index2 !=-1){
    ws2=b.split(".")[1].length;   //ws2=1
  }
  //看谁的小数位数大,谁的小数位数小
  var bigger=(ws1>ws2) ? ws1 : ws2;     //bigger=ws2=1
  var smaller=(ws1<ws2) ? ws1 : ws2;    //smaller=ws1=0
  //计算得到需要补齐的0的个数
  var zerosCount=bigger-smaller;       //zerosCount=1
  //好了,现在开始不管三七二十一,全部去掉小数点
  a=a.replace(".","");       //a="1"
  b=b.replace(".","");       //b="02"
  //比较a和b谁大,比较方法就是看谁是smaller,是smaller的一方后面补0
  if(ws1==smaller){
    for(var i=0;i<zerosCount;i++){
     a+="0";        //a="10"
    }
  }else{
    for(var i=0;i<zerosCount;i++){
      b+="0";
    }
  }
  // 开始计算(字符串转化为数字)
  var sum=parseInt(a)+parseInt(b);     //sum=10+2=12
  //根据较大的小数位数计算倍数
  var beishu=1;
  for(var i=0;i<bigger;i++){
    beishu=beishu*10        //beishu=10
  }
  sum=sum/beishu;           //sum=12/10=1.2
  return sum;

}
console.log(0.1+0.2) //0.30000000000000004
console.log(add(0.1,0.2))//0.3
console.log(add(1,0.2))//1.2
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值