You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为含+、-、*、/、%的计算器实现运算符优先级?

解决计算器运算符优先级问题

你的问题很典型——当前代码是从左到右顺序计算,完全没考虑乘除(*、/、%)比加减(+、-)优先级高的规则,所以计算3+3-4*8+5/6+5时会得到错误结果。

我给你两种可行的实现思路,先讲最直观的分步处理法,再讲更通用的栈方法(适合以后扩展更多运算符)。

方法一:分步处理(先乘除后加减)

核心思路是拆分表达式后分两次遍历:

  • 第一次专门处理所有乘除、取模运算,把计算结果替换掉对应的数字和运算符,生成只含加减和数字的新列表
  • 第二次遍历新列表,处理所有加减运算得到最终结果

修改后的代码如下:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Calculator {
    public String calculateExpression(String expression) {
        // 拆分表达式为数字和运算符(包含%)
        String[] tokens = expression.split("(?=[*/+-])|(?<=[*/+-])");
        List<String> tokenList = new ArrayList<>(Arrays.asList(tokens));

        // 第一步:处理乘除和取模运算
        int i = 0;
        while (i < tokenList.size()) {
            String op = tokenList.get(i);
            if (op.equals("*") || op.equals("/") || op.equals("%")) {
                // 获取运算符前后的数字
                double left = Double.parseDouble(tokenList.get(i - 1));
                double right = Double.parseDouble(tokenList.get(i + 1));
                double result = 0.0;
                switch (op) {
                    case "*":
                        result = Multiplication(left, right);
                        break;
                    case "/":
                        result = Division(left, right);
                        break;
                    case "%":
                        result = Modulus(left, right);
                        break;
                }
                // 替换:移除左数、运算符、右数,插入计算结果
                tokenList.remove(i - 1);
                tokenList.remove(i - 1); // 原运算符现在在i-1位置
                tokenList.remove(i - 1); // 原右数现在在i-1位置
                tokenList.add(i - 1, String.valueOf(result));
                // 移除后列表长度变化,不需要i++,继续检查当前位置
            } else {
                i++;
            }
        }

        // 第二步:处理加减运算
        double dres = Double.parseDouble(tokenList.get(0));
        for (i = 1; i < tokenList.size(); i += 2) {
            String op = tokenList.get(i);
            double val = Double.parseDouble(tokenList.get(i + 1));
            switch (op) {
                case "+":
                    dres = Addition(dres, val);
                    break;
                case "-":
                    dres = Subtraction(dres, val);
                    break;
            }
        }

        return Double.toString(dres);
    }

    // 保留你原来的运算方法
    public double Addition(double d1, double d2) { return d1 + d2; }
    public double Subtraction(double d1, double d2) { return d1 - d2; }
    public double Multiplication(double d1, double d2) { return d1 * d2; }
    public double Division(double d1, double d2) { return d1 / d2; }
    public double Modulus(double d1, double d2) { return d1 % d2; }
}

这个方法逻辑直观,容易理解和调试,完全适配你当前的需求。

方法二:后缀表达式(逆波兰表达式)法

如果以后需要支持括号或者更多复杂运算符(比如平方、开方),后缀表达式会更通用。核心步骤是:

  1. 将中缀表达式(比如3+4*2)转换成后缀表达式(3 4 2 * +)
  2. 遍历后缀表达式,用栈计算最终结果

简化版实现代码如下:

import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

public class Calculator {
    public String calculateExpression(String expression) {
        String[] tokens = expression.split("(?=[*/+-])|(?<=[*/+-])");
        Stack<Double> numStack = new Stack<>();
        Stack<String> opStack = new Stack<>();

        // 定义运算符优先级:乘除模优先级高于加减
        Map<String, Integer> priority = new HashMap<>();
        priority.put("+", 1);
        priority.put("-", 1);
        priority.put("*", 2);
        priority.put("/", 2);
        priority.put("%", 2);

        for (String token : tokens) {
            if (token.matches("-?\\d+(\\.\\d+)?")) { // 匹配数字(支持负数和小数)
                numStack.push(Double.parseDouble(token));
            } else { // 处理运算符
                // 栈顶运算符优先级更高时,先计算再压栈
                while (!opStack.isEmpty() && priority.get(opStack.peek()) >= priority.get(token)) {
                    double right = numStack.pop();
                    double left = numStack.pop();
                    String op = opStack.pop();
                    numStack.push(calculate(left, right, op));
                }
                opStack.push(token);
            }
        }

        // 处理栈中剩余的运算符
        while (!opStack.isEmpty()) {
            double right = numStack.pop();
            double left = numStack.pop();
            String op = opStack.pop();
            numStack.push(calculate(left, right, op));
        }

        return Double.toString(numStack.pop());
    }

    private double calculate(double left, double right, String op) {
        switch (op) {
            case "+": return left + right;
            case "-": return left - right;
            case "*": return left * right;
            case "/": return left / right;
            case "%": return left % right;
            default: throw new IllegalArgumentException("Invalid operator: " + op);
        }
    }

    // 原运算方法可保留,也可直接使用上面的calculate方法
}

测试你的示例表达式

对于3+3-4*8+5/6+5,正确结果应为≈-20.1667,用上面任意一种代码都能得到这个正确结果。

内容的提问来源于stack exchange,提问作者marcus.w

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:25:39