“简单四则运算解释器”题目要求
一、问题描述
实现一个基本的计算器来计算一个简单的字符串表达式的值。注意事项如下:
- 输入是一个字符串表达式(可以假设所给定的表达式都是有效的)
- 字符串表达式可以包含的运算符号为:左括号
(, 右括号), 加号+, 减号- - 可以包含的数字为:非负整数(< 10)
- 字符串中不包含空格
- 处理除法 case 的时候,可以直接省略小数部分结果,只保留整数部分参与后续运算
- 请不要使用内置的库函数
eval
二、测试样例
输入样例:
1+13+4*5/(3+2)4+2*5-2/1(1+(4+5+2)-3)+(6+8)
输出样例:
271223
三、题目解析
3.1代码思路
- 导入及初始化栈:使用栈数据结构来处理表达式的计算,初始化的两个栈:
numbers用于存储数字,operators用于存储运算符。 - 数据处理:遍历输入的字符串表达式,逐个字符进行处理。如果当前字符是数字,将其转换为整数并压入
numbers栈。如果数字是多位数,继续读取后续字符,直到遇到非数字字符。 - 左右括号处理:如果当前字符是左括号
(,将其压入operators栈。如果当前字符是右括号),从operators栈中弹出运算符并进行计算,直到遇到左括号(。 - 处理运算符:- 如果当前字符是运算符(
+,-,*,/),根据运算符的优先级决定是否立即进行计算。如果栈顶运算符的优先级高于或等于当前运算符,从operators栈中弹出运算符并进行计算。然后将当前运算符压入operators栈。最后,遍历完表达式后,处理operators栈中剩余的运算符,直到栈为空。 - 定义
hasPrecedence方法:定义一个静态方法hasPrecedence,用于判断运算符的优先级。
- 如果
op2是括号,返回false。 - 如果
op1是乘法或除法,op2是加法或减法,返回false。 - 否则返回
true。
- 定义
applyOperation方法:定义一个静态方法applyOperation,用于执行具体的计算操作。从numbers栈中弹出两个数字a和b,从operators栈中弹出一个运算符op。根据运算符执行相应的计算,并将结果压入numbers栈。
3.2详细代码
public class Main {
public static int solution(String expression) {
Stack<Integer> numbers = new Stack<>();
Stack<Character> operators = new Stack<>();
for (int i = 0; i < expression.length(); i++) {
char ch = expression.charAt(i);
if (Character.isDigit(ch)) {
// 处理数字
int num = ch - '0';
while (i + 1 < expression.length() && Character.isDigit(expression.charAt(i + 1))) {
num = num * 10 + (expression.charAt(++i) - '0');
}
numbers.push(num);
} else if (ch == '(') {
// 处理左括号
operators.push(ch);
} else if (ch == ')') {
// 处理右括号
while (!operators.isEmpty() && operators.peek() != '(') {
// 计算括号内的表达式
applyOperation(numbers, operators);
}
operators.pop(); // 弹出左括号
} else if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {
// 处理运算符
while (!operators.isEmpty() && hasPrecedence(ch, operators.peek())) {
// 计算优先级高的运算符
applyOperation(numbers, operators);
}
operators.push(ch);
}
}
// 处理剩余的运算符
while (!operators.isEmpty()) {
applyOperation(numbers, operators);
}
return numbers.pop();
}
// 判断运算符优先级
private static boolean hasPrecedence(char op1, char op2) {
if (op2 == '(' || op2 == ')') {
return false;
}
if ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-')) {
return false;
}
return true;
}
// 执行计算操作
private static void applyOperation(Stack<Integer> numbers, Stack<Character> operators) {
int b = numbers.pop();
int a = numbers.pop();
char op = operators.pop();
int result = 0;
switch (op) {
case '+':
result = a + b;
break;
case '-':
result = a - b;
break;
case '*':
result = a * b;
break;
case '/':
result = a / b; // 整数除法
break;
}
numbers.push(result);
}
public static void main(String[] args) {
// 测试用例
System.out.println(solution("1+1") == 2);
System.out.println(solution("3+4*5/(3+2)") == 7);
System.out.println(solution("4+2*5-2/1") == 12);
System.out.println(solution("(1+(4+5+2)-3)+(6+8)") == 23);
}
}
四、知识总结
- 栈的使用:使用两个栈
numbers和operators来处理表达式的计算。 - 优先级处理:通过
hasPrecedence方法判断运算符的优先级,决定是否立即进行计算。 - 计算逻辑:通过
applyOperation方法执行具体的计算操作。 - 多位数处理:在处理数字时,检查是否是多位数,并将其转换为整数。
- 除法处理:在
applyOperation方法中,使用整数除法a / b来确保结果为整数。