mirror of
https://gitee.com/dromara/hutool.git
synced 2026-02-09 09:16:26 +08:00
修复Calculator.conversion方法计算包含%连接一元运算符的计算表达式的结果时逻辑缺陷(pr#4191@Github)
This commit is contained in:
@@ -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 == '(';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user