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 };
  • 相关阅读:
    LeetCode 623. Add One Row to Tree
    LeetCode 894. All Possible Full Binary Trees
    LeetCode 988. Smallest String Starting From Leaf
    LeetCode 979. Distribute Coins in Binary Tree
    LeetCode 814. Binary Tree Pruning
    LeetCode 951. Flip Equivalent Binary Trees
    LeetCode 426. Convert Binary Search Tree to Sorted Doubly Linked List
    LeetCode 889. Construct Binary Tree from Preorder and Postorder Traversal
    LeetCode 687. Longest Univalue Path
    LeetCode 428. Serialize and Deserialize N-ary Tree
  • 原文地址:https://www.cnblogs.com/ZQWelcomeIndex/p/7896883.html
Copyright © 2011-2022 走看看