62

If I've got a string that is a mathematic equation and I want to split it and then calculate it. I know I can use the eval() function to do this, but I'm interested if there's an alternative way to do this - specifically by splitting the strings first. So I've got something like

var myString = "225 + 15 - 10"
var newString = myString.split(" ");

This would turn myString into an array:

["225", "+", "15", "-", "10"];

My next task is to turn all the odd-numbered strings into integers, which I think I could use parseInt(); for. My question is, how do I turn the "+" and "-" into actual arithmetic operators? So that at the end I am left with a mathematic expression which I can calculate?

Is this possible?

adiga
  • 34,372
  • 9
  • 61
  • 83
Allen S
  • 3,471
  • 4
  • 34
  • 46
  • The ugly way would be multiple if statements. – keyser Oct 25 '12 at 21:59
  • 2
    Make a real parser, otherwise this exercise is pretty pointless :) Here's a good article http://parsingintro.sourceforge.net/ – Esailija Oct 25 '12 at 21:59
  • Unless you have an exceptional reason, just `eval` it. – Oliver Moran Oct 25 '12 at 22:02
  • 2
    Somewhat related: http://stackoverflow.com/questions/9729963/javascript-beginner-level-kata-building-a-calculator-using-functions – Cᴏʀʏ Oct 25 '12 at 22:03
  • This may help as well, you are really just looking to build a math parser. This is a common academic exercise in Computer Science curriculums. http://stackoverflow.com/questions/114586/smart-design-of-a-math-parser – Mark At Ramp51 May 11 '16 at 15:29

3 Answers3

104
var math_it_up = {
    '+': function (x, y) { return x + y },
    '-': function (x, y) { return x - y }
}​​​​​​​;

math_it_up['+'](1, 2) == 3;
jonvuri
  • 5,738
  • 3
  • 24
  • 32
  • Hi thanks for that. This would work - but what if the entire string is input by a user? So I don't have the control over what the numbers inside the string are. In other words if this is a calculator and the user punches in "225 + 15 - 10", I split the string up, and take whatever the numbers and operators are and turn them in to a math expression. In the solution you offered - how would I automatically replace x and y -- not define them manually? – Allen S Oct 25 '12 at 22:03
  • Normally I'd go the parser direction (mentioned above by @Esailija) but the context provided in the question makes this a good, simple solution. Edit: for complete control over user input, write a parser. – psema4 Oct 25 '12 at 22:05
  • If `+` and `-` are alternating with numbers you can simply loop through it. – insertusernamehere Oct 25 '12 at 22:05
  • 1
    @user1775598, There are several ways that you could do it. One way would be to simply loop over the string and check hasOwnProperty on your math_it_up object for each element; if it's true, call it with the preceding and succeeding indices in the array as the arguments to the function. Of course, you might still want to verify that those indices exist and are valid numbers... and you'll also want to respect precedence rules if you extend this to `/` and `*`... The more sophisticated and the more robust you make this, the closer it's going to come to a parser. – jonvuri Oct 25 '12 at 22:25
101

JavaScript's eval function was mentioned in a comment by Oliver Morgan and I just wanted to flush out how you could use eval as a solution to your problem.

The eval function takes a string and then returns the value of that string considered as a math operation. For example,

eval("3 + 4")

will return 7 as 3 + 4 = 7.

This helps in your case because you have an array of strings that you want you want to treat as the mathematical operators and operands that they represent.

myArray = ["225", "+", "15", "-", "10"]; 

Without converting any of the strings in your array into integers or operators you could write

eval(myArray[0] + myArray[1] + myArray[2]);

which will translate to

eval("225" + "+" + "15");

which will translate to

eval("225 + 15");

which will return 240, the value of adding 225 to 15.

Or even more generic:

eval(myArray.join(' '));

which will translate to

eval("225 + 15 - 10");

which will return 230, the value of adding 15 to 225 and substract 10. So you can see that in your case it may be possible to skip converting the strings in your array into integers and operators and, as Oliver Morgan said, just eval it.

Community
  • 1
  • 1
Benjamin Conant
  • 1,684
  • 1
  • 14
  • 17
  • I'm thinking of using some "mathy" expression in form validation and a parser is just overkill. Using `eval()` allows me to simply parse some strings such as `<|oh` for validation (where `oh` references another form input class/id/etc). – pspahn Dec 11 '14 at 23:41
  • 5
    But don't use eval() too much. There are a number of reasons why: https://24ways.org/2005/dont-be-eval – Charles Watson Aug 27 '15 at 05:53
  • 2
    Never use eval. For anything. It is a huge security hole in JS. – Daut Sep 14 '17 at 21:50
  • 2
    Although powerful, do not use eval https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval – APengue Jun 29 '18 at 13:32
  • 2
    this could be dangerous if input coming from user – Ali Azhar Oct 28 '18 at 20:26
0

Consider using isNaN(Number(array[x])) and a switch for anything that doesn't satisfy the condition.

undefined
  • 2,051
  • 3
  • 26
  • 47