美文网首页Web开发
JS:学好加、减、乘、除运算,走遍天下都不怕

JS:学好加、减、乘、除运算,走遍天下都不怕

作者: 以气御码 | 来源:发表于2020-07-05 17:11 被阅读0次

    进入我的主页,查看更多JS的分享!
    这是另一种实现方式,更简洁、完整(原先有一篇实现了,可以对比这一篇的代码看看)

    一般涉及到价格的计算,比如商城的下单结算,多数是交由后端来计算的。但是也会有前台的参与,遇到也不要慌,下面的代码直接解决了js的计算问题。
    有问题请在评论区告知,没有就点个赞呗!

    一、加法、减法

    1. 出错的例子

    console.log(0.1 + 0.2);
    //输出:0.30000000000000004,正确结果为0.3
    console.log(0.2 + 0.4)
    //输出:0.6000000000000001,正确结果为0.6
     
    console.log(1.0 - 0.9);
    //输出:0.09999999999999998,正确结果为0.1
    console.log(0.9 - 0.7);
    //输出:0.20000000000000007,正确结果为0.2
    

    2. 解析

    出错是因为浮点数运算的时候,先转化为二进制,用二进制来计算,得到的结果再转回十进制。
    简单理解为js里的非整数运算会出错,下面是解决的代码(推荐非整数的运算都经过处理而不是直接计算)。

    
    //加法运算
    var calcPlus = (num1, num2) => {
      let l1, l2, m;
      try {
        l1 = num1.toString().split(".")[1].length;
      } catch (e) {
        l1 = 0;
      }
      try {
        l2 = num2.toString().split(".")[1].length;
      } catch (e) {
        l2 = 0;
      }
      m = Math.pow(10, Math.max(l1, l2));
      return (num1 * m + num2 * m) / m;
    };
     
    console.log(calcPlus(0.1, 0.2));
    //输出:0.3
    console.log(calcPlus(0.2, 0.4));
    //输出:0.6
    
    
    //减法运算
    var calcSubtract = (num1, num2) => {
      let l1, l2, m;
      try {
        l1 = num1.toString().split(".")[1].length;
      } catch (e) {
        l1 = 0;
      }
      try {
        l2 = num2.toString().split(".")[1].length;
      } catch (e) {
        l2 = 0;
      }
      m = Math.pow(10, Math.max(l1, l2));
      return (num1 * m - num2 * m) / m;
    };
     
    console.log(calcSubtract(1.0, 0.9));
    //输出:0.1
    console.log(calcSubtract(0.9, 0.7));
    //输出:0.2
    

    对比这两段代码会发现,实现原理是一样的:

    • 得到中间值,是两个数字的最大的小数位,并由10的次方转换为实际的值;
    • 最终,数字1、数字2经中间值变为整数,计算后再经中间值得到正确的结果;
    • 比如,0.1 + 0.2 => (0.1x10 + 0.2x10) / 10 = 3 / 10 = 0.3;
    • 比如,0.9 - 0.7 => (0.9x10 - 0.7x10) / 10 = 2 / 10 = 0.2

    二、乘法

    1. 出错的例子

    console.log(19.9 * 100);
    //输出:1989.9999999999998,正确结果为1990
    console.log(79.9 * 100);
    //输出:7990.000000000001,正确结果为7990
    

    2. 解析

    出错的原因,一样是转为二进制后再进行计算。先贴上代码:

    //乘法运算
    var calcMultiply = (num1, num2) => {
      let m = 0;
      try {
        m += num1.toString().split(".")[1].length;
      } catch (e) {}
      try {
        m += num2.toString().split(".")[1].length;
      } catch (e) {}
      return (Number(num1.toString().replace(".", "")) * Number(num2.toString().replace(".", ""))) / Math.pow(10, m);
    };
     
    console.log(calcMultiply(19.9, 100));
    //输出:1990
    console.log(calcMultiply(79.9, 100));
    //输出:7990
    

    实现原理:

    • 得到中间值,是两个数字的小数位之和,并由10的次方转换为实际的值;
    • 将数字1、数字2去除小数点,即变为整数,相乘后除以中间值,得到正确的结果;
    • 比如:19.9 * 100 => (199 * 100) / 10 = 19900 / 10 = 1990

    三、除法

    1. 出错的例子

    console.log(6.6 / 0.2);
    //输出:32.99999999999999,正确结果为33
    console.log(99.9 / 3);
    //输出:33.300000000000004,正确结果为33.3
    

    2. 解析

    出错的原因,一样是转为二进制后再进行计算。先贴上代码:

    //除法运算
    var calcDivide = (num1, num2) => {
      let l1 = 0, l2 = 0;
      try {
        l1 = num1.toString().split(".")[1].length;
      } catch (e) {}
      try {
        l2 = num2.toString().split(".")[1].length;
      } catch (e) {}
      let c = Number(num1.toString().replace(".", "")) / Number(num2.toString().replace(".", ""));
      return calcMultiply(c , Math.pow(10, l2-l1));
    };
     
    console.log(calcDivide (6.6, 0.2));
    //输出:33
    console.log(calcDivide (99.9, 0.3));
    //输出:333
    

    实现原理:

    • 得到中间值,是两个数字的小数位之差,并由10的次方转换为实际的值;注意除法的除数位与被除数位是固定的,因此上面代码是l2-l1;
    • 将数字1、数字2去除小数点,即变为整数,相除后乘以中间值(调用上面的乘法的计算,因为会存在小数),得到正确的结果;
    • 比如:99.9/3 => (999 / 3) * 0.1 = 333 * 0.1 = 33.3

    四、拓展封装(完整代码)

    上面的代码还有重复的地方,那就再进一步封装:

    /**
     * calc.plus 加法运算
     * calc.subtract 减法运算
     * calc.multiply 乘法运算
     * calc.divide 除法运算
     */
     
    var calc = (function () {
      let operation = (num1, num2, op) => {
        let l1, l2, max;
        try {
          l1 = num1.toString().split(".")[1].length;
        } catch (e) {
          l1 = 0;
        }
        try {
          l2 = num2.toString().split(".")[1].length;
        } catch (e) {
          l2 = 0;
        }
        switch (op) {
          case "plus":
            max = Math.pow(10, Math.max(l1, l2));
            return (num1 * max + num2 * max) / max;
          case "subtract":
            max = Math.pow(10, Math.max(l1, l2));
            return (num1 * max - num2 * max) / max;
          case "multiply":
            return (Number(num1.toString().replace(".", "")) * Number(num2.toString().replace(".", ""))) / Math.pow(10, l1 + l2);
          case "divide":
            return operation(Number(num1.toString().replace(".", "")) / Number(num2.toString().replace(".", "")), Math.pow(10, l2 - l1), "multiply");
        }
      };
      let plus = (a, b) => {
        return operation(a, b, "plus");
      };
      let subtract = (a, b) => {
        return operation(a, b, "subtract");
      };
      let multiply = (a, b) => {
        return operation(a, b, "multiply");
      };
      let divide = (a, b) => {
        return operation(a, b, "divide");
      };
      return { plus, subtract, multiply, divide };
    })();
     
    console.log(0.1 + 0.2, calc.plus(0.1, 0.2));
    //输出:0.30000000000000004 0.3
    console.log(0.2 + 0.4, calc.plus(0.2, 0.4));
    //输出:0.6000000000000001 0.6
    console.log(1.0 - 0.9, calc.subtract(1.0, 0.9));
    //输出:0.09999999999999998 0.1
    console.log(0.9 - 0.7, calc.subtract(0.9, 0.7));
    //输出:0.20000000000000007 0.2
    console.log(19.9 * 100, calc.multiply(19.9, 100));
    //输出:1989.9999999999998 1990
    console.log(79.9 * 100, calc.multiply(79.9, 100));
    //输出:7990.000000000001 7990
    console.log(6.6 / 0.2, calc.divide(6.6, 0.2));
    //输出:32.99999999999999 33
    console.log(99.9 / 3, calc.divide(99.9, 3));
    //输出:33.300000000000004 33.3
    

    如果问题,请在评论区留言!


    相关文章

      网友评论

        本文标题:JS:学好加、减、乘、除运算,走遍天下都不怕

        本文链接:https://www.haomeiwen.com/subject/grivqktx.html