js精度丢失解决办法(浮点数产生的原因)

 分类:js知识时间:2023-09-01 07:30:06点击:

web前端工作中经常遇到后端返回数据处理浮点数加减的问题,有时候浮点数的运算结果和我们预想的却不一样,先看个例子:

1、console.log(0.1+0.2);

2、console.log(0.1+0.1);

明眼一看都觉得第1个应该是0.3,第2个应该是0.2;其实第1个实际上却不是0.3,而是0.30000000000000004,看控制台输出如下图所示:

之所以偏离我们的预想是因为浮点数的精度问题导致。

一、浮点数产生的原因

首先就想到计算机能读懂的是二进制,在进行运算的时候,实际上是把数字转换为了二进制进行的,所以我们把0.1和0.2转换为二进制:

0.1 => 0.0001 1001 1001 1001..(无限循环)

0.2 => 0.0011 0011 0011 0011…(无限循环)

这里可以看出转换为二进制是一个无限循环的数字,单在计算机中对于无限循环的数字会进行舍入处理的,进行双精度浮点数的小数部分最多支持52位。然后把两个2进制的数进行运算得出的也是一个二进制数值,最后再把它转换为十进制。保留17位小数,所以0.1+0.2的值就成了 0.30000000000000004。 0.1+0.1的值成了0.20000000000000000,全是0的时候可以省略,就成了0.2。

二、精度丢失解决办法

为了解决这个浮点数精度问题,我们可以把浮点数看成两部分,一个是整数部分,另一个是小数部分。整数部分加减肯定不会出现精度问题,剩下的是小数部分取两者最大的精度进行计算之后再按实际位数截取。下面给出写好的示例:

//比较
function floatCompare(arg1, arg2) {
  var r1, r2, m, n;
  try{r1=arg1.toString().split(".")[1].length} catch(e){r1=0}
  try{r2=arg2.toString().split(".")[1].length} catch(e){r2=0}
  m = Math.pow(10, Math.max(r1, r2));
  var result = (arg1*m-arg2*m) >= 0 ? true : false;
  return result;
}

//加 
function floatAdd(arg1,arg2){ 
  var r1,r2,m; 
  try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0} 
  try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0} 
  m=Math.pow(10,Math.max(r1,r2)); 
  return (arg1*m+arg2*m)/m; 
} 
   
//减 
function floatSub(arg1,arg2){ 
 var r1,r2,m,n; 
 try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0} 
 try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0} 
 m=Math.pow(10,Math.max(r1,r2)); 
 //动态控制精度长度 
 n=(r1>=r2)?r1:r2; 
 return ((arg1*m-arg2*m)/m).toFixed(n); 
} 
   
//乘 
function floatMul(arg1,arg2) { 
 var m=0,s1=arg1.toString(),s2=arg2.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); 
} 
    
//除 
function floatDiv(arg1,arg2){ 
  var t1=0,t2=0,r1,r2; 
  try{t1=arg1.toString().split(".")[1].length}catch(e){} 
  try{t2=arg2.toString().split(".")[1].length}catch(e){} 
    
  r1=Number(arg1.toString().replace(".","")); 
  
  r2=Number(arg2.toString().replace(".","")); 
  return (r1/r2)*Math.pow(10,t2-t1); 
}


除注明外的文章,均为来源:老汤博客,转载请保留本文地址!
原文地址: