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 };
  • 相关阅读:
    神秘人物之comca —— 是否就是我的前车之鉴
    mfc错误:其原因可能是堆被损坏,这说明**.exe中或它加载的任何DLL
    微信公共平台php用$GLOBALS["HTTP_RAW_POST_DATA"]收不到信息解决方法
    2013蓝桥杯初赛c语言专科组题目与答案
    一道2012腾讯实习生笔试题
    文件版权自动注释,自动备份
    算法学习 三 >> 认识算法的效率(循环设计)
    算法学习 二 >> 结构化与面向对象两种算法设计的简略分析(c++/java)
    HTML入门(一)
    算法学习 一 >> 初识
  • 原文地址:https://www.cnblogs.com/ZQWelcomeIndex/p/7896883.html
Copyright © 2011-2022 走看看