修复MathUtil.multiple 方法在大整数乘法运算中整数溢出风险

This commit is contained in:
Will
2025-12-03 10:46:53 +08:00
parent d4510bfeb1
commit 51f1f9de62
2 changed files with 22 additions and 2 deletions

View File

@@ -1692,7 +1692,15 @@ public class NumberUtil {
* @return 最小公倍数
*/
public static int multiple(int m, int n) {
return m * n / divisor(m, n);
// 先计算最大公约数
int gcd = divisor(m, n);
// 使用长整型避免溢出,再转换回整型
long result = (long) m / gcd * (long) n;
// 检查结果是否在int范围内
if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) {
throw new ArithmeticException("Integer overflow: " + m + " * " + n + " / " + gcd);
}
return (int) result;
}
/**

View File

@@ -621,7 +621,7 @@ public class NumberUtilTest {
assertTrue(NumberUtil.isPrimes(2147483647));
assertFalse(NumberUtil.isPrimes(2147483646));
}
@Test
public void range(){
assertFalse(NumberUtil.isIn(new BigDecimal("1"),new BigDecimal("2"),new BigDecimal("12")));
@@ -704,4 +704,16 @@ public class NumberUtilTest {
final boolean equals = NumberUtil.equals(104557543L, 104557544);
assertFalse(equals);
}
@Test
public void testMultipleOverflow() {
int a = 500000;
int b = 600000;
// 原方法使用 a * b / gcd(a, b) 计算a * b 会先溢出,得到最小公倍数为负数
// 使用修改后的multiple方法测试它是否能正确处理这种情况
int result = NumberUtil.multiple(a, b);
// 验证结果必须是正数(两个正数的最小公倍数必须为正)
assertTrue(result > 0);
}
}