核心算法设计
-
基本运算逻辑
-
四则运算算法:使用栈(Stack)处理运算符优先级(如乘除优先于加减)
public double calculate(String expression) { Stack<Double> numbers = new Stack<>(); Stack<Character> operators = new Stack<>(); for (int i = 0; i < expression.length(); i++) { char c = expression.charAt(i); if (Character.isDigit(c)) { // 处理多位数 StringBuilder num = new StringBuilder(); while (i < expression.length() && (Character.isDigit(expression.charAt(i)) || expression.charAt(i) == '.')) { num.append(expression.charAt(i++)); } i--; numbers.push(Double.parseDouble(num.toString())); } else if (c == '(') { operators.push(c); } else if (c == ')') { while (operators.peek() != '(') { processOperation(numbers, operators.pop()); } operators.pop(); // 移除 '(' } else if (isOperator(c)) { // 比较优先级:当前运算符优先级 <= 栈顶则先计算 while (!operators.isEmpty() && getPriority(c) <= getPriority(operators.peek())) { processOperation(numbers, operators.pop()); } operators.push(c); } } while (!operators.isEmpty()) { processOperation(numbers, operators.pop()); } return numbers.pop(); } private void processOperation(Stack<Double> numbers, char op) { double b = numbers.pop(); double a = numbers.pop(); switch (op) { case '+': numbers.push(a + b); break; case '-': numbers.push(a - b); break; case '*': numbers.push(a * b); break; case '/': if (b == 0) throw new ArithmeticException("除零错误"); numbers.push(a / b); break; } }
-
-
高级函数扩展
- 科学计算算法:集成
Math
类实现幂、开方、三角函数public double handleScientificFunc(String func, double num) { return switch (func) { case "sqrt" -> Math.sqrt(num); case "pow" -> Math.pow(num, 2); // 平方 case "sin" -> Math.sin(Math.toRadians(num)); default -> throw new IllegalArgumentException("无效函数"); }; }
- 科学计算算法:集成
关键实现细节
-
表达式解析
- 使用正则表达式拆分输入:
"10+3.2*sin(45)" → ["10", "+", "3.2", "*", "sin", "(", "45", ")"]
- 处理负数:在表达式起始或运算符后出现时标记为负号而非减号。
- 使用正则表达式拆分输入:
-
异常处理
- 自定义异常类提升健壮性:
try { result = calculate(expression); } catch (ArithmeticException e) { System.out.println("错误: " + e.getMessage()); } catch (EmptyStackException e) { System.out.println("表达式不合法"); }
- 自定义异常类提升健壮性:
-
内存功能算法
-
实现
MC
(清除)、MR
(读取)、M+
(累加):private double memory = 0; public void memoryClear() { memory = 0; } public double memoryRecall() { return memory; } public void memoryAdd(double value) { memory += value; }
-
性能与安全优化
-
算法效率
- 时间复杂度:
O(n)
(单次遍历表达式) - 使用
StringBuilder
替代字符串拼接减少内存开销。
- 时间复杂度:
-
输入验证
- 防止SQL注入/XSS攻击(Web版):
if (!expression.matches("[0-9+\-*/().sqrt^sinco]+")) { throw new IllegalArgumentException("非法字符"); }
- 防止SQL注入/XSS攻击(Web版):
-
精度处理
- 用
BigDecimal
替代double
避免浮点误差:BigDecimal a = new BigDecimal("0.1"); BigDecimal b = new BigDecimal("0.2"); System.out.println(a.add(b)); // 0.3
- 用
测试与调试
- 单元测试用例
@Test public void testCalculate() { assertEquals(8.0, calculate("3 + 5")); assertEquals(6.0, calculate("2 * (1 + 2)")); assertEquals(1.0, calculate("sin(90)"), 0.001); // 允许误差 }
- 边界测试
- 超大数:
1e308 * 2
→ 返回Infinity
- 连续运算符:
5+-3
→ 解析为5 + (-3)
- 超大数:
进阶扩展方向
- 支持变量与函数
- 使用
HashMap<String, Double>
存储变量(如π=3.14
)
- 使用
- 表达式可视化
集成JavaFX绘制计算过程树形图
- 历史记录
- 用
LinkedList
保存最近10次计算记录
- 用
引用说明:
- 运算符优先级算法参考《算法导论》(Thomas H. Cormen)
Math
类函数规范源自Oracle官方文档- 安全实践符合OWASP输入验证标准(2025版)
通过分层设计算法模块、严格验证输入、覆盖异常场景,可构建出符合工业级标准的计算器应用,建议结合Swing或JavaFX实现GUI,完整代码参考GitHub开源项目JavaCalculator。
原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/31352.html