题目
实现一个计算器,可以完成下列运算:
- calc(0) => 0
- calc(+2,5) => 7
- calc(-3,*4,1) => -1
- calc(*3,/14,+1,*2,3) => 6
- calc(+3,3,3) => 无效表达式,抛异常
实现
- 思路:遍历字符串,如果当前字符为操作数则压入栈中。否则,就弹出依次弹出栈顶操作数进行数学运算,再将计算后的结果压回栈中,作为下一步数学运算的操作数。如下面伪代码所示:
forEach(input)
if (input[i] is num) {
stack.push()
} else if (input[i] is operator) {
num1 = stack.pop()
num2 = stack.pop()
...
stack.push(result)
}
- 示例:
const numRegexp = /^[0-9]/;
const opStrRegexp = /^([\+\-\*\/])(\d*)/;
function calc(str) {
if (str.length <= 2) {
if (str.length === 1 && numRegexp.test(str)) {
return parseInt(str);
}
throw new Error('Invalid Expression');
}
const stack = [];
const parts = str.split(',');
for (let i = parts.length - 1; i > -1; i--) {
if (numRegexp.test(parts[i])) {
stack.unshift(parts[i]);
} else {
const match = opStrRegexp.exec(parts[i]);
if (match) {
const opStr = match[1];
const rightOpNum = parseInt(stack.pop());
const leftOpNum = match[2] ? parseInt(match[2]) : parseInt(stack.pop());
switch(opStr) {
case '+':
stack.push(leftOpNum + rightOpNum);
break;
case '-':
stack.push(leftOpNum - rightOpNum);
break;
case '/':
stack.push(leftOpNum / rightOpNum);
break;
case '*':
stack.push(leftOpNum * rightOpNum);
break;
default:
throw new Error('Invalid Operator!!!');
}
}
}
}
if (stack.length !== 1) {
throw new Error('Invalid Expression');
}
return stack.pop();
}