求Java实现SRPN(饱和逆波兰表示法)计算器的完整代码示例
SRPN计算器Java实现(饱和逆波兰表示法)
以下是完整的SRPN计算器实现,包含栈运算、要求的所有运算符、溢出饱和处理以及f历史调用功能:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayDeque; import java.util.Deque; import java.util.LinkedList; import java.util.List; public class SRPNCalculator { private final Deque<Integer> operandStack = new ArrayDeque<>(); private final List<Integer> historyNumbers = new LinkedList<>(); private static final int MIN_INT = Integer.MIN_VALUE; private static final int MAX_INT = Integer.MAX_VALUE; public static void main(String[] args) { SRPNCalculator calculator = new SRPNCalculator(); calculator.start(); } public void start() { try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { String input; System.out.println("SRPN计算器已启动,输入数字/运算符/指令,输入'exit'退出"); while ((input = reader.readLine()) != null) { input = input.trim(); if (input.isEmpty()) continue; if ("exit".equalsIgnoreCase(input)) break; processInput(input); } } catch (IOException e) { System.err.println("输入读取错误: " + e.getMessage()); } } private void processInput(String input) { // 按空格拆分输入,支持多token一行输入 String[] tokens = input.split("\\s+"); for (String token : tokens) { if (token.matches("-?\\d+")) { // 处理数字 int num = Integer.parseInt(token); operandStack.push(num); historyNumbers.add(num); } else if (token.equals("=")) { // 输出栈顶元素 if (!operandStack.isEmpty()) { System.out.println(operandStack.peek()); } else { System.err.println("错误:栈为空,无法输出"); } } else if (token.startsWith("f")) { // 处理f指令,格式如f1、f3 if (token.length() < 2) { System.err.println("错误:f指令格式错误,需后跟数字,如f1"); continue; } String indexStr = token.substring(1); if (!indexStr.matches("\\d+")) { System.err.println("错误:f指令后的参数必须是正整数"); continue; } int index = Integer.parseInt(indexStr) - 1; // 转0索引 if (index < 0 || index >= historyNumbers.size()) { System.err.println("错误:历史数字索引超出范围"); continue; } int num = historyNumbers.get(index); operandStack.push(num); } else { // 处理运算符 processOperator(token); } } } private void processOperator(String operator) { if (operandStack.size() < 2) { System.err.println("错误:栈中元素不足,无法执行" + operator + "运算"); return; } int b = operandStack.pop(); int a = operandStack.pop(); int result = 0; boolean overflow = false; switch (operator) { case "+": result = a + b; // 检查加法溢出 overflow = (b > 0 && a > MAX_INT - b) || (b < 0 && a < MIN_INT - b); break; case "-": result = a - b; // 检查减法溢出 overflow = (b < 0 && a > MAX_INT + b) || (b > 0 && a < MIN_INT + b); break; case "*": result = a * b; // 检查乘法溢出 overflow = (a != 0 && b != 0 && (result / a != b)); break; case "%": if (b == 0) { System.err.println("错误:模运算除数不能为0"); operandStack.push(a); operandStack.push(b); return; } result = a % b; // 处理负数模运算的一致性,保证结果符号与被除数一致 if ((a < 0 && b > 0) || (a > 0 && b < 0)) { result += b; } break; case "^": // 幂运算,只处理整数幂,底数为负时指数需为正整数 if (b < 0) { System.err.println("错误:幂运算指数不能为负数"); operandStack.push(a); operandStack.push(b); return; } if (a == 0 && b == 0) { System.err.println("错误:0的0次方无意义"); operandStack.push(a); operandStack.push(b); return; } result = 1; for (int i = 0; i < b; i++) { // 每一步检查溢出 if (result > MAX_INT / a || result < MIN_INT / a) { overflow = true; break; } result *= a; } break; default: System.err.println("错误:不支持的运算符" + operator); operandStack.push(a); operandStack.push(b); return; } // 饱和处理:溢出时设置为最大/最小值 if (overflow) { result = (operator.equals("+") || operator.equals("*") || (operator.equals("^") && b > 0)) ? MAX_INT : MIN_INT; } operandStack.push(result); historyNumbers.add(result); } }
关键功能说明
- 栈运算逻辑:使用
Deque<Integer>实现栈结构,完全适配逆波兰表达式后进先出的运算规则 - 溢出饱和处理:对加减乘幂运算做溢出检查,溢出时自动将结果截断到
Integer.MAX_VALUE或Integer.MIN_VALUE - f指令实现:用
List<Integer>记录所有输入过的有效数字(包括运算结果),输入fN时调用第N个历史数字(N从1开始计数) - 多输入支持:支持单token单行或多token单行输入(比如输入
3 3 * =可直接输出9) - 异常场景处理:覆盖了除数为0、0的0次方、栈元素不足、无效指令等异常情况
使用示例
- 基础运算:输入
3 3 * =,输出9 - 多步运算:输入
3 3 * 4 4 * + =,输出25 - f指令调用:先输入
5 7,再输入f1 f2 * =,输出35
内容的提问来源于stack exchange,提问作者user21476558
相关产品推荐
相关产品推荐

