From 497eb125d8d713a4cb4f37cc75cd4fa18fd28c4f Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 27 Dec 2025 13:21:30 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D`Calculator.conversion`?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E8=AE=A1=E7=AE=97=E5=8C=85=E5=90=AB%?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E4=B8=80=E5=85=83=E8=BF=90=E7=AE=97=E7=AC=A6?= =?UTF-8?q?=E7=9A=84=E8=AE=A1=E7=AE=97=E8=A1=A8=E8=BE=BE=E5=BC=8F=E7=9A=84?= =?UTF-8?q?=E7=BB=93=E6=9E=9C=E6=97=B6=E9=80=BB=E8=BE=91=E7=BC=BA=E9=99=B7?= =?UTF-8?q?=EF=BC=88pr#4191@Github=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/hutool/v7/core/math/Calculator.java | 23 +++++++++---- .../hutool/v7/core/math/CalculatorTest.java | 32 +++++++++++++++++++ 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/math/Calculator.java b/hutool-core/src/main/java/cn/hutool/v7/core/math/Calculator.java index a516d618b3..c97fd99725 100644 --- a/hutool-core/src/main/java/cn/hutool/v7/core/math/Calculator.java +++ b/hutool-core/src/main/java/cn/hutool/v7/core/math/Calculator.java @@ -116,7 +116,8 @@ public class Calculator { count++; } } - if (count > 1 || (count == 1 && !isOperator(arr[currentIndex]))) {// 最后一个字符不是括号或者其他运算符的则加入后缀式栈中 + //新增防止数组越界 + if (count > 1 || (count == 1 && currentIndex < arr.length && !isOperator(arr[currentIndex]))) {// 最后一个字符不是括号或者其他运算符的则加入后缀式栈中 postfixStack.push(new String(arr, currentIndex, count)); } @@ -165,12 +166,20 @@ public class Calculator { * @return 结果 */ private BigDecimal calculate(final String firstValue, final String secondValue, final char currentOp) { + final BigDecimal first = NumberUtil.toBigDecimal(firstValue); + final BigDecimal second = NumberUtil.toBigDecimal(secondValue); + + //添加除零检查并提供明确错误信息 + if ((currentOp == '/' || currentOp == '%') && second.compareTo(BigDecimal.ZERO) == 0) { + throw new ArithmeticException("Division by zero: cannot divide " + firstValue + " by zero"); + } + return switch (currentOp) { - case '+' -> NumberUtil.add(firstValue, secondValue); - case '-' -> NumberUtil.sub(firstValue, secondValue); - case '*' -> NumberUtil.mul(firstValue, secondValue); - case '/' -> NumberUtil.div(firstValue, secondValue); - case '%' -> NumberUtil.toBigDecimal(firstValue).remainder(NumberUtil.toBigDecimal(secondValue)); + case '+' -> NumberUtil.add(first, second); + case '-' -> NumberUtil.sub(first, second); + case '*' -> NumberUtil.mul(first, second); + case '/' -> NumberUtil.div(first, second); + case '%' -> first.remainder(second); default -> throw new IllegalStateException("Unexpected value: " + currentOp); }; } @@ -260,6 +269,6 @@ public class Calculator { * 判断给定位置前一个非空字符是否为运算符或左括号(用于判定是否为一元上下文) */ private static boolean isPrevCharOperatorOrLeftParen(final char c) { - return c == '+' || c == '-' || c == '*' || c == '/' || c == '('; + return c == '%' || c == '+' || c == '-' || c == '*' || c == '/' || c == '('; } } diff --git a/hutool-core/src/test/java/cn/hutool/v7/core/math/CalculatorTest.java b/hutool-core/src/test/java/cn/hutool/v7/core/math/CalculatorTest.java index a7688c6ec9..9064ae5878 100644 --- a/hutool-core/src/test/java/cn/hutool/v7/core/math/CalculatorTest.java +++ b/hutool-core/src/test/java/cn/hutool/v7/core/math/CalculatorTest.java @@ -113,4 +113,36 @@ public class CalculatorTest { final double conversion4 = Calculator.conversion("-3"); assertEquals(-3.0, conversion4, 0.001); } + + @Test + public void percentOperatorTest() { + //基础 % 运算 + assertEquals(1.0, Calculator.conversion("10 % 3"), 0.001); + + // % 运算符后跟连续的一元运算符的情况 + assertEquals(1.0, Calculator.conversion("10 % +-3"), 0.001); + assertEquals(1.0, Calculator.conversion("10 % -3"), 0.001); + + // 带括号的 % 后一元负号 + assertEquals(1.0, Calculator.conversion("10 % (-3)"), 0.001); + + // % 与 * / 的优先级测试 + assertEquals(2.0, Calculator.conversion("10 * 5 % 3"), 0.001); + assertEquals(1.0, Calculator.conversion("20 / 5 % 3"), 0.001); + + //连续 % 运算 + assertEquals(2.0, Calculator.conversion("100 % 7 % 3"), 0.001); + + // % 与 + - 混合运算 + assertEquals(13.0, Calculator.conversion("10 + 15 % 4"), 0.001); + + //负数操作数的 % 运算 + assertEquals(-1.0, Calculator.conversion("-10 % 3"), 0.001); + + // 两个负数的 % 运算 + assertEquals(-1.0, Calculator.conversion("-10 % -3"), 0.001); + + // 小数的 % 运算 + assertEquals(0.9, Calculator.conversion("10.5 % 3.2"), 0.001); + } }