Java简易计算器开发求助:无法实现功能及MDAS优先级规则
解决Java简易计算器的MDAS优先级与运行问题
嘿,作为编程新手搞计算器确实容易在运算符优先级和输入解析上卡壳,我来帮你一步步搞定这个问题!
首先,你提到要遵循MDAS规则(乘除优先于加减),同时实现输入1 + 1输出2,核心难点在于不能按输入顺序直接计算,得先处理乘除,再处理加减。下面是具体的解决方案:
1. 核心思路:双栈法处理优先级
最经典的表达式求值方法就是用两个栈:一个存数字,一个存运算符。逻辑大概是这样:
- 遇到数字就压入数字栈
- 遇到运算符时,和栈顶的运算符比较优先级:
- 如果当前运算符优先级低于或等于栈顶,就弹出栈顶运算符和两个数字计算,结果压回数字栈
- 重复这个过程直到栈顶运算符优先级更低,再把当前运算符压入栈
- 最后把栈里剩下的运算符依次计算,数字栈的最后一个元素就是结果
2. 完整代码实现
下面是包含输入解析、优先级处理和计算的完整代码,你可以直接测试:
import java.util.Scanner; import java.util.Stack; public class SimpleCalculator { // 定义运算符优先级:乘除>加减 private static int getPriority(char op) { switch (op) { case '+': case '-': return 1; case '*': case '/': return 2; default: return 0; } } // 执行运算:注意栈的后进先出,b是右操作数,a是左操作数 private static double applyOp(char op, double b, double a) { switch (op) { case '+': return a + b; case '-': return a - b; case '*': return a * b; case '/': if (b == 0) { throw new ArithmeticException("不能除以零"); } return a / b; default: return 0; } } // 解析并计算表达式 private static double calculate(String expression) { Stack<Double> numStack = new Stack<>(); Stack<Character> opStack = new Stack<>(); for (int i = 0; i < expression.length(); i++) { char c = expression.charAt(i); // 跳过输入中的空格 if (Character.isWhitespace(c)) { continue; } // 处理数字(包括多位数和小数) if (Character.isDigit(c) || c == '.') { StringBuilder numStr = new StringBuilder(); // 把连续的数字/小数点拼接成完整数字 while (i < expression.length() && (Character.isDigit(expression.charAt(i)) || expression.charAt(i) == '.')) { numStr.append(expression.charAt(i)); i++; } i--; // 回退一位,因为循环里i已经自增了 numStack.push(Double.parseDouble(numStr.toString())); // 这里添加你需要的调试输出,匹配示例格式 System.out.println("index= " + i + " " + numStr); } // 处理左括号(可选支持括号运算) else if (c == '(') { opStack.push(c); } // 处理右括号:计算到左括号为止 else if (c == ')') { while (opStack.peek() != '(') { numStack.push(applyOp(opStack.pop(), numStack.pop(), numStack.pop())); } opStack.pop(); // 弹出左括号 } // 处理运算符 else { while (!opStack.isEmpty() && getPriority(opStack.peek()) >= getPriority(c)) { numStack.push(applyOp(opStack.pop(), numStack.pop(), numStack.pop())); } opStack.push(c); } } // 处理栈中剩余的运算符 while (!opStack.isEmpty()) { numStack.push(applyOp(opStack.pop(), numStack.pop(), numStack.pop())); } return numStack.pop(); } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Enter: "); String input = scanner.nextLine().replace("=", ""); // 去掉输入里的=号 try { double result = calculate(input); System.out.println(result); } catch (Exception e) { System.out.println("输入有误:" + e.getMessage()); } scanner.close(); } }
3. 关键细节说明
- 优先级判断:
getPriority方法给乘除赋值2,加减赋值1,确保乘除先被计算 - 数字解析:用
StringBuilder拼接连续的数字和小数点,支持多位数和小数 - 操作数顺序:栈是后进先出,所以弹出的第一个数字是右操作数,第二个是左操作数(比如计算
a - b,弹出的顺序是b、a) - 调试输出:代码里已经添加了类似你示例的
index= X 数字输出,完全匹配你的预期格式
4. 测试示例
输入2+1=,程序会输出:
Enter: 2+1= index= 0 2 index= 2 1 3.0
输入1+2*3=,会正确输出7.0(严格遵循MDAS规则)
内容的提问来源于stack exchange,提问作者Kolin
相关产品推荐
相关产品推荐

