我必须评估下面的表达式,这些表达式在字符串变量中可用,而不使用eval或外部库或第三方软件包:
"abs(add(multiply(-1,multiply(-1,subtract(89,19880))),subtract(add(12,add(247,45986)),98)))"
有人可以建议如何使用Javascript或jQuery完成它吗?
答案 0 :(得分:0)
使用堆栈实现传统的表达式评估方法 - 操作数堆栈,运算符堆栈。从堆栈推送弹出。这是我能想到的最佳方式。
答案 1 :(得分:0)
我并没有真正打扰使代码高效或防弹(这里可能存在一些错误),但这里有一个关于如何做到这一点的例子。您可以将中缀表达式转换为后缀表示形式作为标记数组,然后执行该后缀表示的计算。
注意:我不允许对带有空格的表达式进行正确的标记,但如果不是您需要的话,您可以更改它。
var logEl = document.getElementById('log'),
expInput = document.querySelector('input');
document.querySelector('button').addEventListener('click', function () {
updateEvaluationResult(expInput.value);
});
updateEvaluationResult(expInput.value);
function updateEvaluationResult(exp) {
var logMsg;
try { logMsg = evaluateExpression(exp); }
catch (e) {
logMsg = e.message + ('charIndex' in e? ' (char index ' + e.charIndex + ')' : '')
}
logEl.textContent = logMsg;
}
function evaluateExpression(exp) {
var functions = {
abs: Math.abs,
multiply: function(num1, num2) {
return num1 * num2;
},
substract: function(num1, num2) {
return num1 - num2;
},
add: function(num1, num2) {
return num1 + num2;
}
};
return (evaluateExpression = function(exp) {
var fn;
return postfixTokenizationOf(exp).reduce(function(resultStack, token) {
if (typeof token == 'number') resultStack.push(token);
else {
fn = functions[token];
if (!fn) throw new Error("'" + token + "' is an invalid function");
resultStack.push(functions[token].apply(
null,
resultStack.splice(resultStack.length - fn.length)
));
}
return resultStack;
}, []).pop();
})(exp);
}
function postfixTokenizationOf(exp) {
if (!exp) return [];
var stack = [],
output = [],
indexOf = [].indexOf,
tokenRx = /[^-(),\d]+|[(),]|[-\d]+/g,
functionTokenRx = /[^-(),\d]+/,
charTokenHandlers = {
'(': stack.push.bind(stack, '('),
')': handleRightParenthesis,
',': handleArgSeperator
},
charTokenHandler, token, match;
while (match = tokenRx.exec(exp)) {
token = match[0];
if ((charTokenHandler = charTokenHandlers[token])) {
charTokenHandler();
continue;
}
if (isNumeric(token)) {
output.push(+token);
continue;
}
handleFunction();
}
if (popStackUntilOneOfTokenFound('()')) throwMismatchedParenthesisError();
return output;
function handleFunction() {
var nextCharIndex = tokenRx.lastIndex;
if (exp[nextCharIndex] != '(') throwError('expected a function call');
else stack.push(token);
}
function handleRightParenthesis() {
if (!popStackUntilOneOfTokenFound('(')) throwMismatchedParenthesisError();
stack.pop();
if (isFunction(topOfStack())) output.push(stack.pop());
}
function handleArgSeperator() {
if (!popStackUntilOneOfTokenFound('(')) throwError(
'mismatched parenthesis or misplaced argument seperator'
);
}
function popStackUntilOneOfTokenFound(tokenChars) {
var t;
while (indexOf.call(tokenChars, t = topOfStack()) == -1 && t) output.push(stack.pop());
return !!stack.length;
}
function throwError(msg) {
var err = new Error(msg);
err.charIndex = tokenRx.lastIndex;
throw err;
}
function throwMismatchedParenthesisError() {
throwError('mismatched parenthesis');
}
function topOfStack() {
return stack[stack.length - 1];
}
function isFunction(token) {
return functionTokenRx.test(token);
}
function isNumeric(token) {
return parseFloat(token) == token;
}
}
input {
width: 500px;
}
<label>Exp:
<input type="text" value="abs(add(multiply(-1,multiply(-1,substract(89,19880))),substract(add(12,add(247,45986)),98)))">
</label>
<div id="log"></div>
<button>Evaluate</button>
答案 2 :(得分:-1)
最简单的方法是创建一堆能够满足您需求的函数,然后eval()
代码。
function calc(str){
function subtract(a, b){
return a-b;
}
function add(a, b){
return a+b;
}
function mulitiply(a, b){
return a*b;
}
function divide(a, b){
return a/b;
}
function abs(a){
return Math.abs(a);
}
return eval('('+str+')');
}
console.log(calc('abs(add(multiply(-1,multiply(-1,subtract(89,19880))),subtract(add(12,add(247,45986)),98)))'));
答案 3 :(得分:-1)
如何编写自定义函数?
function add(ad1, ad2) {
var sum = parseFloat(ad1) + parseFloat(ad2);
return sum;
}
function subtract(sub1, sub2) {
var sub = parseFloat(sub1) - parseFloat(sub2);
return sub;
}
function multiply(mlt1, mlt2) {
var mlt = parseFloat(mlt1) * parseFloat(mlt2);
return mlt;
}
function abs(ab1) {
var abs = Math.abs(parseFloat(ab1));
return abs;
}
function evaluatethis(exp) {
document.write('<script>alert(' + exp + ');</' + 'script>');
}
evaluatethis("abs(add(multiply(-1,multiply(-1,subtract(89,19880))),subtract(add(12,add(247,45986)),98)))");