题解—简单四则运算解析器|豆包MarsCode AI刷题

91 阅读3分钟

整体思路

该代码的目的是实现一个能够解析并计算包含数字、四则运算符(+-*/)以及括号的字符串表达式的值的计算器功能,且不依赖 Java 的内置eval函数。核心思路是利用两个栈,一个用于存储操作数(数字),另一个用于存储运算符,通过按照运算符的优先级和括号的规则来逐步处理表达式,最终得到计算结果。

代码结构及功能解析

solution方法

public static int solution(String expression) {
    return calculate(expression);
}

solution方法作为对外的接口,它接收一个表示四则运算表达式的字符串参数expression,然后直接调用calculate方法进行实际的计算,并返回最终的计算结果。

calculate方法

private static int calculate(String expression) {
    java.util.Stack<Integer> numStack = new java.util.Stack<>();
    java.util.Stack<Character> opStack = new java.util.Stack<>();
    int i = 0;

    while (i < expression.length()) {
        char currentChar = expression.charAt(i);

            if (Character.isDigit(currentChar)) {
                int num = 0;
                while (i < expression.length() && Character.isDigit(currentChar)) {
                    num = num * 10 + (currentChar - '0');
                    i++;
                    if (i < expression.length()) {
                        currentChar = expression.charAt(i);
                    }
                }
                numStack.push(num);
            } else if (currentChar == '(') {
                opStack.push(currentChar);
                i++;
            } else if (currentChar == ')') {
                while (!opStack.isEmpty() && opStack.peek()!= '(') {
                    performOperation(numStack, opStack);
                }
                opStack.pop();
                i++;
            } else {
                while (!opStack.isEmpty() && precedence(currentChar) <= precedence(opStack.peek())) {
                    performOperation(numStack, opStack);
                }
                opStack.push(currentChar);
                i++;
            }
    }

    while (!opStack.isEmpty()) {
        performOperation(numStack, opStack);
    }

    return numStack.pop();
}
  • 首先,创建了两个栈:numStack用于存储数字,opStack用于存储运算符。然后通过一个循环遍历输入的表达式字符串expression
  • 当遇到数字字符时,通过一个内层循环将连续的数字字符转换为对应的整数,并将其压入numStack
  • 当遇到左括号(时,将其直接压入opStack,表示进入一个新的运算子表达式范围。
  • 当遇到右括号)时,会不断从opStack中弹出运算符并执行相应运算(通过调用performOperation方法),直到遇到左括号(,然后将左括号弹出,完成这一层括号内表达式的计算。
  • 当遇到运算符(+-*/)时,会根据运算符的优先级与opStack栈顶运算符的优先级比较。如果当前运算符优先级小于等于栈顶运算符优先级,就先执行栈顶运算符对应的运算(同样通过调用performOperation方法),然后再将当前运算符压入opStack。否则,直接将当前运算符压入opStack
  • 最后,当表达式遍历完后,如果opStack还有剩余运算符,就依次执行这些运算符对应的运算,直到opStack为空。此时numStack栈顶元素就是表达式的最终计算结果,通过numStack.pop()返回。

performOperation方法

private static void performOperation(java.util.Stack<Integer> numStack, java.util.Stack<Character> opStack) {
    char op = opStack.pop();
    int right = numStack.pop();
    int left = numStack.pop();

    if (op == '+') {
        numStack.push(left + right);
    } else if (op == '-') {
        numStack.push(left - right);
    } else if (op == '*') {
        numStack.push(left * right);
    } else if (op == '/') {
        numStack.push(left / right);
    }
}

这个方法用于执行具体的四则运算操作。它从opStack中弹出一个运算符,从numStack中弹出两个操作数(先弹出的是右操作数,后弹出的是左操作数),然后根据弹出的运算符进行相应的加、减、乘、除运算,并将结果压回numStack

precedence方法

private static int precedence(char op) {
    if (op == '+' || op == '-') {
        return 1;
    } else if (op == '*' || op == '/') {
        return 2;
    }
    return 0;
}

precedence方法用于确定运算符的优先级。它接收一个运算符字符作为参数,返回该运算符的优先级值。其中+-的优先级为1*/的优先级为2,其他情况返回0。这个优先级值在calculate方法中用于比较运算符的优先级,以决定运算的执行顺序。