zoukankan      html  css  js  c++  java
  • Js浮点运算存在精度问题

         记得在某一次项目中,运用js进行一系列算数运算,计算中会存在浮点类型,就单纯的进行了计算,最后在测试过程中,主管在核对数据的时候发现计算的结果是有问题的,于是就很纳闷,在网上搜索找到了答案  ,http://www.css88.com/archives/7340

          原因:计算过程中的十进制的数会先转换二进制,进行计算,然后将结果在转换为十进制(往往有些浮点类型数值转换为二进制是无穷的),所以往往也会导致出现精度问题

    那么如何解决呢?

    网上提供的方案如下:

      1 /**
      2  ** 加法函数,用来得到精确的加法结果
      3  ** 说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
      4  ** 调用:accAdd(arg1,arg2)
      5  ** 返回值:arg1加上arg2的精确结果
      6  **/
      7 function accAdd(arg1, arg2) {
      8     var r1, r2, m, c;
      9     try {
     10         r1 = arg1.toString().split(".")[1].length;
     11     }
     12     catch (e) {
     13         r1 = 0;
     14     }
     15     try {
     16         r2 = arg2.toString().split(".")[1].length;
     17     }
     18     catch (e) {
     19         r2 = 0;
     20     }
     21     c = Math.abs(r1 - r2);
     22     m = Math.pow(10, Math.max(r1, r2));
     23     if (c > 0) {
     24         var cm = Math.pow(10, c);
     25         if (r1 > r2) {
     26             arg1 = Number(arg1.toString().replace(".", ""));
     27             arg2 = Number(arg2.toString().replace(".", "")) * cm;
     28         } else {
     29             arg1 = Number(arg1.toString().replace(".", "")) * cm;
     30             arg2 = Number(arg2.toString().replace(".", ""));
     31         }
     32     } else {
     33         arg1 = Number(arg1.toString().replace(".", ""));
     34         arg2 = Number(arg2.toString().replace(".", ""));
     35     }
     36     return (arg1 + arg2) / m;
     37 }
     38  
     39 //给Number类型增加一个add方法,调用起来更加方便。
     40 Number.prototype.add = function (arg) {
     41     return accAdd(arg, this);
     42 };
     43 
     44 /**
     45  ** 减法函数,用来得到精确的减法结果
     46  ** 说明:javascript的减法结果会有误差,在两个浮点数相减的时候会比较明显。这个函数返回较为精确的减法结果。
     47  ** 调用:accSub(arg1,arg2)
     48  ** 返回值:arg1加上arg2的精确结果
     49  **/
     50 function accSub(arg1, arg2) {
     51     var r1, r2, m, n;
     52     try {
     53         r1 = arg1.toString().split(".")[1].length;
     54     }
     55     catch (e) {
     56         r1 = 0;
     57     }
     58     try {
     59         r2 = arg2.toString().split(".")[1].length;
     60     }
     61     catch (e) {
     62         r2 = 0;
     63     }
     64     m = Math.pow(10, Math.max(r1, r2)); //last modify by deeka //动态控制精度长度
     65     n = (r1 >= r2) ? r1 : r2;
     66     return ((arg1 * m - arg2 * m) / m).toFixed(n);
     67 }
     68  
     69 // 给Number类型增加一个mul方法,调用起来更加方便。
     70 Number.prototype.sub = function (arg) {
     71     return accMul(arg, this);
     72 };
     73 
     74 
     75 /**
     76  ** 乘法函数,用来得到精确的乘法结果
     77  ** 说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。
     78  ** 调用:accMul(arg1,arg2)
     79  ** 返回值:arg1乘以 arg2的精确结果
     80  **/
     81 function accMul(arg1, arg2) {
     82     var m = 0, s1 = arg1.toString(), s2 = arg2.toString();
     83     try {
     84         m += s1.split(".")[1].length;
     85     }
     86     catch (e) {
     87     }
     88     try {
     89         m += s2.split(".")[1].length;
     90     }
     91     catch (e) {
     92     }
     93     return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
     94 }
     95  
     96 // 给Number类型增加一个mul方法,调用起来更加方便。
     97 Number.prototype.mul = function (arg) {
     98     return accMul(arg, this);
     99 };
    100 
    101 
    102 /** 
    103  ** 除法函数,用来得到精确的除法结果
    104  ** 说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。
    105  ** 调用:accDiv(arg1,arg2)
    106  ** 返回值:arg1除以arg2的精确结果
    107  **/
    108 function accDiv(arg1, arg2) {
    109     var t1 = 0, t2 = 0, r1, r2;
    110     try {
    111         t1 = arg1.toString().split(".")[1].length;
    112     }
    113     catch (e) {
    114     }
    115     try {
    116         t2 = arg2.toString().split(".")[1].length;
    117     }
    118     catch (e) {
    119     }
    120     with (Math) {
    121         r1 = Number(arg1.toString().replace(".", ""));
    122         r2 = Number(arg2.toString().replace(".", ""));
    123         return (r1 / r2) * pow(10, t2 - t1);
    124     }
    125 }
    126  
    127 //给Number类型增加一个div方法,调用起来更加方便。
    128 Number.prototype.div = function (arg) {
    129     return accDiv(this, arg);
    130 };
  • 相关阅读:
    HDU1720 A+B Coming
    HDU1390 ZOJ1383 Binary Numbers
    HDU1390 ZOJ1383 Binary Numbers
    HDU2504 又见GCD
    HDU2504 又见GCD
    HDU1335 POJ1546 UVA389 UVALive5306 ZOJ1334 Basically Speaking
    HDU1335 POJ1546 UVA389 UVALive5306 ZOJ1334 Basically Speaking
    HDU1020 ZOJ2478 Encoding
    HDU1020 ZOJ2478 Encoding
    HDU2097 Sky数
  • 原文地址:https://www.cnblogs.com/ZQWelcomeIndex/p/7896883.html
Copyright © 2011-2022 走看看