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 };
  • 相关阅读:
    HTML5项目笔记7:使用HTML5 WebStorage API构建与.NET对应的会话机制 Hello
    论设计模式和分析模式
    昨天我做了点什么事情啊?
    时间,时间,还是时间
    人生需要规划
    突然想起今天的博客汇报没写
    昨天看了熊猫大侠
    双休日往往会忘了写日志
    老婆说我是缺心眼!
    要下班了才想起没写报告
  • 原文地址:https://www.cnblogs.com/ZQWelcomeIndex/p/7896883.html
Copyright © 2011-2022 走看看