如何在没有 eval 的情况下在 javascript 中编写计算器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32292231/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to code a calculator in javascript without eval
提问by spb
So, I've searched high and low, and I can't find an answer to this. I've attempted it about three times and gotten a basic one cranked out by basically storing the input in an array as a string, parsing the numbers, then switching on the operator, in order to evaluate the integers, but I'm having a really hard time figuring out the chaining logic. Does anyone have any suggestions? Of maybe even just the psuedocode? I really don't want to use eval. Thanks a lot
所以,我搜索了高低,我找不到答案。我已经尝试了大约 3 次,并通过将输入作为字符串存储在数组中,解析数字,然后打开运算符,以评估整数,得到了一个基本的,但我有一个真的很难弄清楚链接逻辑。有没有人有什么建议?甚至可能只是伪代码?我真的不想使用 eval。非常感谢
回答by Stuart
For a simple calculator with only 5 operators (^, *, /, +, -) and no parentheses, you can do something like this. First, it is convenient to turn the string into an array of numbers and operators. Then, we go through the array looking for each operator in order of precedence, and applying the operator to the numbers preceding and following the it.
对于只有 5 个运算符(^、*、/、+、-)且没有括号的简单计算器,您可以执行以下操作。首先,将字符串转换为数字和运算符的数组很方便。然后,我们遍历数组,按优先顺序查找每个运算符,并将运算符应用于它前后的数字。
function parseCalculationString(s) {
// --- Parse a calculation string into an array of numbers and operators
var calculation = [],
current = '';
for (var i = 0, ch; ch = s.charAt(i); i++) {
if ('^*/+-'.indexOf(ch) > -1) {
if (current == '' && ch == '-') {
current = '-';
} else {
calculation.push(parseFloat(current), ch);
current = '';
}
} else {
current += s.charAt(i);
}
}
if (current != '') {
calculation.push(parseFloat(current));
}
return calculation;
}
function calculate(calc) {
// --- Perform a calculation expressed as an array of operators and numbers
var ops = [{'^': (a, b) => Math.pow(a, b)},
{'*': (a, b) => a * b, '/': (a, b) => a / b},
{'+': (a, b) => a + b, '-': (a, b) => a - b}],
newCalc = [],
currentOp;
for (var i = 0; i < ops.length; i++) {
for (var j = 0; j < calc.length; j++) {
if (ops[i][calc[j]]) {
currentOp = ops[i][calc[j]];
} else if (currentOp) {
newCalc[newCalc.length - 1] =
currentOp(newCalc[newCalc.length - 1], calc[j]);
currentOp = null;
} else {
newCalc.push(calc[j]);
}
console.log(newCalc);
}
calc = newCalc;
newCalc = [];
}
if (calc.length > 1) {
console.log('Error: unable to resolve calculation');
return calc;
} else {
return calc[0];
}
}
var calculateButton = document.getElementById('calculate'),
userInput = document.getElementById('userInput'),
result = document.getElementById('result');
calculateButton.addEventListener('click', function() {
result.innerHTML = "The answer is " + calculate(parseCalculationString(userInput.value));
});
<input type="text" id="userInput" />
<input type="button" value="Calculate" id="calculate" />
<div id="result"></div>
(jsfiddle). To allow parentheses, you could tell the calculate
function to check for parentheses before it starts looking for any of the other operators, then recursively call itself on the expression within each set of parentheses. The parsing function can also be improved e.g. removing any white space and dealing with errors.
(jsfiddle)。要允许使用括号,您可以告诉calculate
函数在开始查找任何其他运算符之前检查括号,然后在每组括号内的表达式上递归调用自身。解析功能也可以改进,例如删除任何空白和处理错误。