Evaluating a string as a mathematical expression in JavaScript

前端 未结 16 2007
我在风中等你
我在风中等你 2020-11-22 03:34

How do I parse and evaluate a mathematical expression in a string (e.g. \'1+1\') without invoking eval(string) to yield its numerical value?

<
相关标签:
16条回答
  • 2020-11-22 04:04

    You can use the JavaScript Expression Evaluator library, which allows you to do stuff like:

    Parser.evaluate("2 ^ x", { x: 3 });
    

    Or mathjs, which allows stuff like:

    math.eval('sin(45 deg) ^ 2');
    

    I ended up choosing mathjs for one of my projects.

    0 讨论(0)
  • 2020-11-22 04:09

    You can do + or - easily:

    function addbits(s) {
      var total = 0,
          s = s.match(/[+\-]*(\.\d+|\d+(\.\d+)?)/g) || [];
          
      while (s.length) {
        total += parseFloat(s.shift());
      }
      return total;
    }
    
    var string = '1+23+4+5-30';
    console.log(
      addbits(string)
    )

    More complicated math makes eval more attractive- and certainly simpler to write.

    0 讨论(0)
  • 2020-11-22 04:10

    Try AutoCalculator https://github.com/JavscriptLab/autocalculate Calculate Inputs value and Output By using selector expressions

    Just add an attribute for your output input like data-ac="(#firstinput+#secondinput)"

    No Need of any initialization just add data-ac attribute only. It will find out dynamically added elements automatically

    FOr add 'Rs' with Output just add inside curly bracket data-ac="{Rs}(#firstinput+#secondinput)"

    0 讨论(0)
  • 2020-11-22 04:12

    An alternative to the excellent answer by @kennebec, using a shorter regular expression and allowing spaces between operators

    function addbits(s) {
        var total = 0;
        s = s.replace(/\s/g, '').match(/[+\-]?([0-9\.\s]+)/g) || [];
        while(s.length) total += parseFloat(s.shift());
        return total;
    }
    

    Use it like

    addbits('5 + 30 - 25.1 + 11');
    

    Update

    Here's a more optimised version

    function addbits(s) {
        return (s.replace(/\s/g, '').match(/[+\-]?([0-9\.]+)/g) || [])
            .reduce(function(sum, value) {
                return parseFloat(sum) + parseFloat(value);
            });
    }
    
    0 讨论(0)
  • 2020-11-22 04:14

    This is a little function I threw together just now to solve this issue - it builds the expression by analyzing the string one character at a time (it's actually pretty quick though). This will take any mathematical expression (limited to +,-,*,/ operators only) and return the result. It can handle negative values and unlimited number operations as well.

    The only "to do" left is to make sure it calculates * & / before + & -. Will add that functionality later, but for now this does what I need...

    /**
    * Evaluate a mathematical expression (as a string) and return the result
    * @param {String} expr A mathematical expression
    * @returns {Decimal} Result of the mathematical expression
    * @example
    *    // Returns -81.4600
    *    expr("10.04+9.5-1+-100");
    */ 
    function expr (expr) {
    
        var chars = expr.split("");
        var n = [], op = [], index = 0, oplast = true;
    
        n[index] = "";
    
        // Parse the expression
        for (var c = 0; c < chars.length; c++) {
    
            if (isNaN(parseInt(chars[c])) && chars[c] !== "." && !oplast) {
                op[index] = chars[c];
                index++;
                n[index] = "";
                oplast = true;
            } else {
                n[index] += chars[c];
                oplast = false;
            }
        }
    
        // Calculate the expression
        expr = parseFloat(n[0]);
        for (var o = 0; o < op.length; o++) {
            var num = parseFloat(n[o + 1]);
            switch (op[o]) {
                case "+":
                    expr = expr + num;
                    break;
                case "-":
                    expr = expr - num;
                    break;
                case "*":
                    expr = expr * num;
                    break;
                case "/":
                    expr = expr / num;
                    break;
            }
        }
    
        return expr;
    }
    
    0 讨论(0)
  • 2020-11-22 04:14

    You could use a for loop to check if the string contains any invalid characters and then use a try...catch with eval to check if the calculation throws an error like eval("2++") would.

    function evaluateMath(str) {
      for (var i = 0; i < str.length; i++) {
        if (isNaN(str[i]) && !['+', '-', '/', '*', '%', '**'].includes(str[i])) {
          return NaN;
        }
      }
      
      
      try {
        return eval(str)
      } catch (e) {
        if (e.name !== 'SyntaxError') throw e
        return NaN;
      }
    }
    
    console.log(evaluateMath('2 + 6'))

    or instead of a function, you could set Math.eval

    Math.eval = function(str) {
      for (var i = 0; i < str.length; i++) {
        if (isNaN(str[i]) && !['+', '-', '/', '*', '%', '**'].includes(str[i])) {
          return NaN;
        }
      }
      
      
      try {
        return eval(str)
      } catch (e) {
        if (e.name !== 'SyntaxError') throw e
        return NaN;
      }
    }
    
    console.log(Math.eval('2 + 6'))

    0 讨论(0)
提交回复
热议问题