tags:

views:

92

answers:

2

If I have an arithmetic expression as a string ("2+3*4/5"), is there a way to get this computed with the JavaScript Math object without parsing that entire string to separate everything out?

Edit: For now, I'm just concerned about supporting +-*/ with order of operations. I'm open to eval if we can piece together a regular expression to address security.

+3  A: 

You could use some regex parsing to check that there's nothing evil in the string, then just eval.

With just simple arithmetic operations, a safe regex would be:

s.match(/^[-*/+0-9]+$/)

Note this won't validate that the expression is balanced in terms of operands and operators (i.e. it would okay "+2*"), but it will stop any weird code injections.

p00ya
eval seems perfect. Are there are any solid prewritten lines of regex available online to parse for security reasons? I'm no regex master.
chimerical
how complex are your expressions? Do you need to use any of the Math. constants or functions (e.g. PI, sqrt)? Specify in your question and I'll update (I'm sure others will too).
p00ya
+1  A: 

eval() should be adequate, but I'd be wary of it. There is no other built-in solution, though. Just for kicks, I threw together a really simple parser for that sort of arithmetic expression, in JavaScript. Full source here: http://gist.github.com/332477

Basic mechanism is to split on each operator, in order of precedence low->high, and then recursively evaluate each chunk, with a parseInt at the base level, and combine with a simple array reduction on the results, using the operator from the split. Here's the core function (sum, negasum, dividend, product are just array reduce functions for each operator):

 calc = function(input) {
    if (input.indexOf("+") >= 0) {
      return sum(input.split("+"));
    } else if (input.indexOf("-") >= 0) {
      return negasum(input.split("-"));
    } else if (input.indexOf("*") >= 0) {
      return product(input.split("*"));
    } else if (input.indexOf("/") >= 0) {
      return dividend(input.split("/"));
    } else {
      return parseInt(input, 10);
    }
 };

Only supports positive integers, doesn't support parens.

Results for your example (from the console):

  calc("2+3*4/5") -> 4.4
  eval("2+3*4/5") -> 4.4
bcherry
nifty. ________
Plynx