”简单四则运算解析器“题目分析|豆包MarsCode AI刷题

103 阅读3分钟

一、题目分析

本题的核心在于模拟计算器的运算规则,按照正确的运算顺序对给定的字符串表达式进行求值。运算顺序遵循数学中的常规规则,即先计算括号内的表达式,再处理乘除运算,最后进行加减运算。 为了实现这一目标,我们采用了栈的数据结构。具体来说,使用两个栈:一个用于存储操作数(数值),另一个用于存储运算符。在遍历表达式字符串的过程中: - 当遇到数字时,需要将连续的数字字符转换为对应的整数并压入操作数栈。这要求我们通过循环来准确识别完整的数字。 - 遇到括号时,左括号直接压入运算符栈,而右括号则触发对括号内表达式的计算。通过不断从运算符栈弹出运算符并应用到操作数栈的操作数上,直到遇到对应的左括号并将其弹出,以此完成括号内表达式的求值。 - 对于运算符,要先判断其与运算符栈顶运算符的优先级关系。如果栈顶运算符优先级大于或等于当前运算符优先级,就先对栈顶运算符进行计算,然后再将当前运算符压入栈。这样能保证乘除运算先于加减运算执行。

扩展思考 在完成基本功能的实现后,我们可以从以下几个方面对这个计算器进行扩展:

1. 支持更多运算符:比如增加取模运算符“%”、幂运算符“^”等。这就需要重新定义运算符的优先级,并在处理运算符的逻辑中增加对这些新运算符的支持,确保它们能按照正确的顺序参与运算。

2. 处理错误情况:目前的代码在输入合法表达式时能正常工作,但对于非法表达式,如括号不匹配、除数为零等情况,并没有进行有效的处理。我们可以增加错误检测机制,当遇到这些错误时,抛出相应的异常或返回特定的错误提示信息,使程序更加健壮。

3. 支持变量:允许表达式中出现变量,比如“x + 2 * y”。这需要引入变量存储机制,可能还需要结合某种赋值操作来确定变量的值,使计算器能够处理更复杂、更具通用性的表达式。

4. 浮点数支持:目前的计算只保留整数结果,若要支持浮点数运算,需要对数字的处理逻辑进行调整,包括在栈中存储浮点数以及在进行运算时按照浮点数的运算规则进行操作。 通过对本题目的深入分析和这些扩展思考,我们可以进一步完善这个简单字符串表达式计算器,使其具备更强大的功能和更广泛的适用性,以满足更多实际场景下的计算需求。

import java.util.Stack;

public class Main {
    public static int solution(String expression) {
        Stack<Integer> values = 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 = 0;
                while (i < expression.length() && Character.isDigit(expression.charAt(i))) {
                    num = num * 10 + (expression.charAt(i) - '0');
                    i++;
                }
                i--;
                values.push(num);
            } else if (ch == '(') {
                operators.push(ch);
            } else if (ch == ')') {
                while (!operators.isEmpty() && operators.peek()!= '(') {
                    applyOperator(operators, values);
                }
                if (!operators.isEmpty() && operators.peek() == '(') {
                    operators.pop();
                }
            } else if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {
                while (!operators.isEmpty() && precedence(operators.peek()) >= precedence(ch)) {
                    applyOperator(operators, values);
                }
                operators.push(ch);
            }
        }

        while (!operators.isEmpty()) {
            applyOperator(operators, values);
        }

        return values.pop();
    }

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

    private static void applyOperator(Stack<Character> operators, Stack<Integer> values) {
        char operator = operators.pop();
        int right = values.pop();
        int left = values.pop();
        if (operator == '+') {
            values.push(left + right);
        } else if (operator == '-') {
            values.push(left - right);
        } else if (operator == '*') {
            values.push(left * right);
        } else if (operator == '/') {
            values.push(left / right);
        }
    }

    public static void main(String[] args) {
        // You can add more test cases here
        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);
    }
}