本文介绍一种将数字与运算符分别存储在两个列表中,再按从左到右顺序(不考虑优先级)依次计算的简洁实现方法,适用于简易计算器场景,并提供可直接运行的 Java 示例代码,帮助开发者快速掌握操作数按序计算的核心思路。
在开发基础计算器时,常见做法是将数字和运算符分离存储。例如,输入字符串 "10+5*3-2",首先提取出数字列表 ["10", "5", "3", "2"] 和运算符列表 ["+", "*", "-"]。注意,本实现采用严格的从左到右顺序计算——即不遵循数学中乘除优先于加减的规则。这样一来,计算过程等价于 ((10 + 5) * 3) - 2 = 43.0。这正是所谓“操作数按序计算”(operands in order)的核心思路,适合入门级表达式求值场景。
下面直接给出一个简洁的 Java 实现,注释和边界检查都已完善,拿来即可直接运行:
import java.util.*;
public class SimpleCalculator {
/**
* 按从左到右顺序计算:result = ((num0 op0 num1) op1 num2) op2 num3 ...
* @param numbers 非空数字字符串列表(至少含1个元素)
* @param operators 运算符列表,长度应为 numbers.size() - 1
* @return 计算结果
*/
public static double evaluate(List numbers, List operators) {
if (numbers.isEmpty()) throw new IllegalArgumentException("Numbers list cannot be empty");
if (operators.size() != numbers.size() - 1) {
throw new IllegalArgumentException("Operators count must be exactly numbers count minus one");
}
double result = Double.parseDouble(numbers.get(0));
for (int i = 0; i < operators.size(); i++) {
double nextNum = Double.parseDouble(numbers.get(i + 1));
char op = operators.get(i).charAt(0);
switch (op) {
case '+': result += nextNum; break;
case '-': result -= nextNum; break;
case '*': result *= nextNum; break;
case '/':
if (Math.abs(nextNum) < 1e-10) {
throw new ArithmeticException("Division by zero");
}
result /= nextNum;
break;
default:
throw new IllegalArgumentException("Unsupported operator: " + op);
}
}
return result;
}
// 使用示例
public static void main(String[] args) {
List postNumbers = new ArrayList<>(Arrays.asList("10", "5", "3", "2"));
List postOperators = List.of("+", "*", "-");
double result = evaluate(postNumbers, postOperators);
System.out.println(result); // 输出:43.0
}
}
✅ 关键设计说明:
- 初始值取第一个数字,后续每一轮都用当前结果与下一个数字按对应运算符进行运算,实现高效迭代;
- 运算符列表长度必须严格等于数字列表长度减一,否则逻辑失效——该校验已在代码中显式处理,增强鲁棒性;
- 对除零、非法运算符及输入边界均做了显式校验,有效提升代码的健壮性与可维护性;
- 不支持括号或优先级——如需标准数学表达式解析(例如 10+5*3-2 应得到 23.0),则需改用中缀转后缀(逆波兰)或递归下降解析器等高级方案。
