JS浮点运算的精度问题

今天说一下js中 0.1 + 0.2 不等于 0.3 的问题
有些同学没有遇到过这类问题,想试试的同学可以试一下下面的代码

console.log(0.1 + 0.2);  // 0.30000000000000004
console.log(0.3 - 0.1);  // 0.19999999999999998

是不是很有意思,为什么会出现这样的情况呢,简单总结一下

其实不光加法和减法运算,乘法和除法也会出现这样的情况,有人说是不是js计算有问题,当然不是,js这么厉害的语言怎么会有这种低级错误,总的来说是js浮点数运算的精度问题。

具体原因是
你的电脑在计算时,用的时二进制浮点运算,但是你输入的时十进制的数,两者在进行转化时,并不会那么完美,有时候能得到正确的结果,有时就不那么幸运了,比如下面代码

console.log(0.7 + 0.1);  // 0.7999999999999999
console.log(0.6 - 0.2);  // 0.8

其实遇到这种问题,也特别好解决,比如下面最暴力的方法

console.log((0.1 + 0.2).toFixed(1));   // 0.3
console.log((0.3 - 0.1).toFixed(1));   // 0.2

还有比较缓和一点的方法,比如0.1+0.2,先把0.1和0.2都乘10,加完之后再除10,如下代码也能实现。

console.log((0.1 * 10 + 0.2 * 10)/10)   // 0.3

还可以自己封装点函数来解决这个问题,这种方法网上有很多,下面列几个,仅供参考。

// 两数求和
function add(num1,num2){
  var r1,r2,m;
  try{
    r1 = num1.toString().split('.')[1].length;
  }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;
}
console.log(0.1 + 0.2)     // 0.30000000000000004
console.log(add(0.1, 0.2)) // 0.3

// 两数相减
function subtract(num1,num2){
  var r1,r2,m;
  try{
    r1 = num1.toString().split('.')[1].length;
  }catch(e){
    r1 = 0;
  }
  try{
    r2=num2.toString().split(".")[1].length;
  }catch(e){
    r2=0;
  }
  m=Math.pow(10,Math.max(r1,r2));
  n=(r1>=r2)?r1:r2;
  return (Math.round(num1*m-num2*m)/m).toFixed(n);
}
console.log(0.3 - 0.1)           // 0.19999999999999998
console.log(subtract(0.3, 0.1))  // 0.2

// 两数相除
function divide(num1,num2){
  var t1,t2,r1,r2;
  try{
    t1 = num1.toString().split('.')[1].length;
  }catch(e){
    t1 = 0;
  }
  try{
    t2=num2.toString().split(".")[1].length;
  }catch(e){
    t2=0;
  }
  r1=Number(num1.toString().replace(".",""));
  r2=Number(num2.toString().replace(".",""));
  return (r1/r2)*Math.pow(10,t2-t1);
}
console.log(0.3 / 0.1)        // 2.9999999999999996
console.log(divide(0.3, 0.1)) // 3

// 两数相乘
function multiply(num1,num2){
  var m=0,s1=num1.toString(),s2=num2.toString(); 
  try{m+=s1.split(".")[1].length}catch(e){};
  try{m+=s2.split(".")[1].length}catch(e){};
  return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m);
}
console.log(45.6*13)            // 592.8000000000001
console.log(multiply(45.6, 13)) // 592.8
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值