Day16 精密

像计算机这样仪器,做这样的四则运算
0.1+0.2 = 0.30000000000000004
-9007199254740991-8 = -9007199254741000
19.99*100 = 1998.9999999999998
99.98/10 = 9.998000000000001
……

由于部分语言采用IEEE 754标准表示数字精度(大部分为64位)
有0舍1入的情况导致数值不准确。

当数字处于Number​.MAX_SAFE_INTEGER与Number.MIN_SAFE_INTEGER之间计算则能正确显示
以下函数通过将小数转换为整数,再进行四则运算来规避精度丢失的问题。


    /** 
     * 加法运算,避免数据相加小数点后产生多位数和计算精度损失。 
     * 
     * @param num1 加数1 
     * @param num2 加数2 
     */
    function numAdd (num1, num2) {
      var baseNum, baseNum1, baseNum2;
      try {
        baseNum1 = num1.toString().split(".")[1].length;
      } catch (e) {
        baseNum1 = 0;
      }
      try {
        baseNum2 = num2.toString().split(".")[1].length;
      } catch (e) {
        baseNum2 = 0;
      }
      baseNum = Math.pow(10, Math.max(baseNum1, baseNum2));
      // 这样直接乘会有乘法精度的问题,例如
      // console.log(4274.77*100);//输出427477.00000000006
      //return (num1 * baseNum + num2 * baseNum) / baseNum;
      return (numMulti(num1, baseNum) + numMulti(num2, baseNum)) / baseNum;
    };
    /** 
      * 减法运算,避免数据相减小数点后产生多位数和计算精度损失。 
      * 
      * @param num1 被减数 
      * @param num2 减数 
      */
    function numSub (num1, num2) {
      var baseNum, baseNum1, baseNum2;
      var precision;// 精度 
      try {
        baseNum1 = num1.toString().split(".")[1].length;
      } catch (e) {
        baseNum1 = 0;
      }
      try {
        baseNum2 = num2.toString().split(".")[1].length;
      } catch (e) {
        baseNum2 = 0;
      }
      baseNum = Math.pow(10, Math.max(baseNum1, baseNum2));
      precision = (baseNum1 >= baseNum2) ? baseNum1 : baseNum2;
      //return ((num1 * baseNum - num2 * baseNum) / baseNum).toFixed(precision);
      return (numMulti(num1, baseNum) - numMulti(num2, baseNum) / baseNum).toFixed(precision);
    };
    /** 
      * 乘法运算,避免数据相乘小数点后产生多位数和计算精度损失。 
      * 
      * @param num1 被乘数 
      * @param num2 乘数 
      */
    function numMulti (num1, num2) {
      var baseNum = 0;
      try {
        baseNum += num1.toString().split(".")[1].length;
      } catch (e) {
      }
      try {
        baseNum += num2.toString().split(".")[1].length;
      } catch (e) {
      }
      return Number(num1.toString().replace(".", "")) * Number(num2.toString().replace(".", "")) / Math.pow(10, baseNum);
    };
    /** 
      * 除法运算,避免数据相除小数点后产生多位数和计算精度损失。 
      * 
      * @param num1 被除数 
      * @param num2 除数 
      */
    function numDiv (num1, num2) {
      var baseNum1 = 0, baseNum2 = 0;
      var baseNum3, baseNum4;
      try {
        baseNum1 = num1.toString().split(".")[1].length;
      } catch (e) {
        baseNum1 = 0;
      }
      try {
        baseNum2 = num2.toString().split(".")[1].length;
      } catch (e) {
        baseNum2 = 0;
      }
      with (Math) {
        baseNum3 = Number(num1.toString().replace(".", ""));
        baseNum4 = Number(num2.toString().replace(".", ""));
        return (baseNum3 / baseNum4) * pow(10, baseNum2 - baseNum1);
      }
    };

参考:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1. 二进制和八进制表示法 ES6 提供了二进制和八进制数值的新的写法,分别用前缀0b(或0B)和0o(或0O)...
    焦迈奇阅读 2,860评论 0 0
  • 1.JavaScript变量 变量(Variables)在程序中用于存储数据,我们可以将数据存入变量,并在将来替换...
    天真即是正义阅读 3,375评论 0 3
  • 特别说明,为便于查阅,文章转自https://github.com/getify/You-Dont-Know-JS...
    杀破狼real阅读 1,567评论 0 0
  • 第 2 章值 数组( array)、字符串( string)和数字( number)是一个程序最基本的组成部分 2...
    不系流年系乾坤阅读 2,622评论 0 0
  • 电影分享 遇到刷题瓶颈,或自我怀疑时,可以去看看这部影片,会感受到满满的力量,亲测有效~ ❤️ 幸福来敲门❤️ 链...
    活性炭GBS阅读 1,950评论 0 0

友情链接更多精彩内容