views:

222

answers:

5

If I have a string '1+1' is there a way, other than eval(string) to get the numerical value of it i.e. I want to turn '1+1' into 2.

+4  A: 

Somebody has to parse that string. If it's not the interpreter (via eval) then it'll need to be you, writing a parsing routine to extract numbers, operators, and anything else you want to support in a mathematical expression.

So, no, there isn't any (simple) way without eval. If you're concerned about security (because the input you're parsing isn't from a source you control), maybe you can check the input's format (via a whitelist regex filter) before passing it to eval?

bdukes
It's not security that bothers me ( I already have a regexp for the job), it's more the load on the browser as I have to process a lot of strings like this. Could a custom parser feasibly be faster than eval()?
wheresrhys
@wheresrhys: Why would you think your parser, written in JS, is going to be faster than the system provided one (optimized, probably written in C or C++)?
Mehrdad Afshari
eval is by far the fastest way to do this. However, a regexp is generally not sufficient to ensure security.
levik
A: 

Here is nice an example implementation...

m0sa
+2  A: 

// 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';
addbits(string)

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

kennebec
+1 - Probably a bit more general than what I went with, but it won't work for my situation as I may have something like 1+-2, and I want the regex to exclude invalid statements too (I think yours would allow something like "+3+4+")
wheresrhys
A: 

I've eventually gone for this solution, which works for summing positive and negative integers (and with a little modification to the regex will work for decimals too):

function sum(string) {
  return (string.match(/^(-?\d+)(\+-?\d+)*$/)) ? string.split('+').stringSum() : NaN;
}   

Array.prototype.stringSum = function() {
    var sum = 0;
    for(var k=0, kl=this.length;k<kl;k++)
    {
        sum += +this[k];
    }
    return sum;
}

I'm not sure if it's faster than eval(), but as I have to carry out the operation lots of times I'm far more comfortable runing this script than creating loads of instances of the javascript compiler

wheresrhys
Although `return` cannot be used inside an expression, `sum("+1")` returns *NaN*.
Gumbo
Always foregt whether return has to or can't go inside a ternary expression. I'd like to exclude "+1" because although it 'should' evaluate as a number, it's not really an example of a mathematical sum in the everyday sense. My code is designed to both evaluate and filter for allowable strings.
wheresrhys
A: 

I've recently done this in C# (no Eval() for us...) by evaluating the expression in Reverse Polish Notation (that's the easy bit). The hard part is actually parsing ths string and turning it into Reverse Polish Notation. I used the Shunting Yard algorithm as there's a great example on Wikipedia and pseudocode. I found it really simple to implement both and I'd recommend that if you've not already found a solution or are looking at alternatives.

RichK