web前端:js精准计算

    作者: fingersnow 更新于: 2020-03-24 21:53:08

    Web开发

      当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的。计算机中的二进制则是一个非常微小的开关,用1来表示“开”,0来表示“关”。

      js精准计算

      varnumA=0.1;

      varnumB=0.2;

      alert(numA+numB);

      0.1+0.2=0.30000000000000004。

      计算精度误差问题(和二进制相关)。

      对于浮点数的四则运算,几乎所有的编程语言都会有类似精度误差的问题,只不过在C++/C#/java这些语言中已经封装好了方法来避免精度的问题,而Javascript是一门弱类型的语言,从设计思想上就没有对浮点数有个严格的数据类型,所以精度误差的问题就显得格外突出。

      我们先把0.1和0.2转换成二进制看看:

      0.1=>0.0001100110011001…(无限循环)

      0.2=>0.0011001100110011…(无限循环)

      双精度浮点数的小数部分最多支持52位,所以两者相加之后得到这么一串0.0100110011001100110011001100110011001100110011001100因浮点数小数位的限制而截断的二进制数字,这时候,我们再把它转换为十进制,就成了0.30000000000000004。

      如何解决呢?

      首先将数乘以10的幂次方去掉小数位得到可以转化二进制的整数,计算之后再还原。

      /**

      **除法函数,用来得到精确的除法结果

      **说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。

      **调用:accDiv(arg1,arg2)

      **返回值:arg1除以arg2的精确结果

      **/

      functionaccDiv(arg1,arg2){

      vart1=0,t2=0,r1,r2;

      try{

      t1=arg1.toString().split(".")[1].length;

      }

      catch(e){

      }

      try{

      t2=arg2.toString().split(".")[1].length;

      }

      catch(e){

      }

      with(Math){

      r1=Number(arg1.toString().replace(".",""));

      r2=Number(arg2.toString().replace(".",""));

      return(r1/r2)*Math.pow(10,t2-t1);

      }

      }

      /**

      **加法函数,用来得到精确的加法结果

      **说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。

      **调用:accAdd(arg1,arg2)

      **返回值:arg1加上arg2的精确结果

      **/

      functionaccAdd(arg1,arg2){

      varr1,r2,m,c;

      try{

      r1=arg1.toString().split(".")[1].length;

      }

      catch(e){

      r1=0;

      }

      try{

      r2=arg2.toString().split(".")[1].length;

      }

      catch(e){

      r2=0;

      }

      c=Math.abs(r1-r2);

      m=Math.pow(10,Math.max(r1,r2));

      if(c>0){

      varcm=Math.pow(10,c);

      if(r1>r2){

      arg1=Number(arg1.toString().replace(".",""));

      arg2=Number(arg2.toString().replace(".",""))*cm;

      }else{

      arg1=Number(arg1.toString().replace(".",""))*cm;

      arg2=Number(arg2.toString().replace(".",""));

      }

      }else{

      arg1=Number(arg1.toString().replace(".",""));

      arg2=Number(arg2.toString().replace(".",""));

      }

      return(arg1+arg2)/m;

      }

      /**

      **乘法函数,用来得到精确的乘法结果

      **说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。

      **调用:accMul(arg1,arg2)

      **返回值:arg1乘以arg2的精确结果

      **/

      functionaccMul(arg1,arg2){

      varm=0,s1=arg1.toString(),s2=arg2.toString();

      try{

      m+=s1.split(".")[1].length;

      }

      catch(e){

      }

      try{

      m+=s2.split(".")[1].length;

      }

      catch(e){

      }

      returnNumber(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m);

      }

      二进制是计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”,由18世纪德国数理哲学大师莱布尼兹发现。

课课家教育

未登录