Safe evaluation of arithmetic expressions in Javascript
You can try JavaScript Expression Evaluator:
This library is a modified version of
Raphael Graf’s ActionScript Expression
Parser. When I wrote the JavaScript
Function Plotter, I wanted a better
alternative to using JavaScript’s eval
function. There’s no security risk
currently, because you can only run
code in your own browser, but it’s not
as convenient for math (Math.pow(2^x)
instead of 2^x, etc.).
Then your code will be like that:
console.info ( Parser.evaluate( "2 * (3 + 4)" ) ); //prints 14
The source code is on GitHub and it's published on npm as expr-eval
. Can be used like so:
import { Parser } from 'expr-eval';
console.log(Parser.evaluate("2 * (3 + 4)")); // 14
Evaluating a string as a mathematical expression in JavaScript
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
Evaluate an Equation in Javascript, without eval()
I only really know two alternatives, one is to use a script
element that is dynamically written to the page, e.g.:
function evaluate(formula)
{
var script = document.createElement("script");
script.type = "text/javascript";
script.text = "window.__lr = " + formula + ";";
document.body.appendChild(script);
document.body.removeChild(script);
var r = window.__lr;
return r;
}
The other would be to use new Function(...)
:
function evaluate3(formula)
{
var func = new Function("return " + formula);
return func();
}
But I don't think you'll find something that yields similar performance to eval
: http://jsperf.com/alternative-evaluation
The performance of eval
varies across browsers and platforms, have you got a specific browser/platform combination in mind? The newer javascript engines in improved browsers will offer optimised eval
:
This is only a limited set of tests on a few UAs, but it should give you an idea of how it performs in different environments.
How do I check if a given string from a user is a valid arithmetic equation?
I'd set up a function that checks for the following:
- Invalid pairs of adjacent characters, such as
*^
,-)
, and+/
, while allowing other unspecified combinations (such as((
,--
,+(-(
) - Incorrect parentheses, whether that be the incorrect number of open vs close, or closing parentheses with no corresponding opening ones.
- Non-numeric or infinite (
Infinity
keyword) values between specified, allowable operators
document.querySelector("input").addEventListener("keyup", function() { document.getElementById("output").innerHTML = isValid(this.value);});
function isValid(str) { var invalidOperatorPairs = ["**", "*/", "/*", "//", "()", "^^", "^/", "/^", "^*", "*^", "-)", "+)", "*)", "/*", "^)", "-*", "-/", "-^", "+*", "+/", "+^", "(*", "(/", "(^","/)","*)","+)","-)","^)"] str = "(" + str + ")"; var open = 0; for (var i = 0, len = str.length; i < len; i++) { var curr = str[i]; if (curr === "(") { open += 1; } else if (curr === ")") { open -= 1; if (open < 0) { return false } } if (i > 0) { for (var j = 0, oplen = invalidOperatorPairs.length; j < oplen; j++) { if (str[i - 1] == invalidOperatorPairs[j][0] && curr == invalidOperatorPairs[j][1]) { return false } } } } if (open !== 0) return false; var sections = str.split(/[\+\-\*\/\^\)\(]/g); for (i = 0, len = sections.length; i < len; i++) { if ((sections[i].length > 0) && !(Number(sections[i]) !== NaN && isFinite(sections[i]))) { return false } } return true;}
<input type="text" value="" /><div id="output"></div>
Related Topics
How to Check If String Contains Substring
Use $Http Inside Custom Provider in App Config, Angular.Js
Triggering a JavaScript Click() Event at Specific Coordinates
Replacing Spaces with Underscores in JavaScript
JavaScript to Sort Contents of Select Element
How to Test If a String Is JSON or Not
Iterate Over Object Literal Values
What Are the Current Cookie Limits in Modern Browsers
Add Onclick Event to Newly Added Element in JavaScript
Calling Setstate in a Loop Only Updates State 1 Time
Javascript: How to Pass Object by Value
Remove All Special Characters Except Space from a String Using JavaScript
Fix Node Position in D3 Force Directed Layout
Why Does Isnan(" ") (String with Spaces) Equal False
This' Does Not Work Properly in Another Event. I'm Clueless as to Why
Fastest Way to Check a String Contain Another Substring in JavaScript