1. 概述
本文将介绍 Guava 库中实用的数学运算工具类。Guava 提供了四个核心数学工具类:
- IntMath - 处理 int 类型运算
- LongMath - 处理 long 类型运算
- BigIntegerMath - 处理 BigInteger 类型运算
- DoubleMath - 处理 double 类型运算
2. IntMath 工具类
IntMath
专注于整数运算,提供了一系列避免溢出和简化数学计算的方法。下面逐一解析核心方法:
2.1. binomial(int n, int k)
计算二项式系数 C(n,k)。当结果超出 int 范围时直接返回 Integer.MAX_VALUE
,避免溢出。公式:n!/(k!(n-k)!)
@Test
public void whenBinomialOnTwoInt_shouldReturnResultIfUnderInt() {
int result = IntMath.binomial(6, 3);
assertEquals(20, result);
}
@Test
public void whenBinomialOnTwoInt_shouldReturnIntMaxIfOVerflowInt() {
int result = IntMath.binomial(Integer.MAX_VALUE, 3);
assertEquals(Integer.MAX_VALUE, result);
}
2.2. ceilingPowerOfTwo(int x)
返回大于等于 x 的最小 2 的幂。例如 x=20 时返回 32(因为 2^4=16 < 20 < 32=2^5)
@Test
public void whenCeilPowOfTwoInt_shouldReturnResult() {
int result = IntMath.ceilingPowerOfTwo(20);
assertEquals(32, result);
}
2.3. checkedAdd(int a, int b) 及同类方法
执行加法运算,但会检测溢出。当溢出时抛出 ArithmeticException
,避免静默错误。同类方法包括:
checkedMultiply
(乘法)checkedPow
(幂运算)checkedSubtract
(减法)
@Test
public void whenAddTwoInt_shouldReturnTheSumIfNotOverflow() {
int result = IntMath.checkedAdd(1, 2);
assertEquals(3, result);
}
@Test(expected = ArithmeticException.class)
public void whenAddTwoInt_shouldThrowArithmeticExceptionIfOverflow() {
IntMath.checkedAdd(Integer.MAX_VALUE, 100);
}
2.4. divide(int p, int q, RoundingMode mode)
带舍入模式的除法运算。当除不尽且未指定舍入模式时抛出异常。
@Test
public void whenDivideTwoInt_shouldReturnTheResultForCeilingRounding() {
int result = IntMath.divide(10, 3, RoundingMode.CEILING);
assertEquals(4, result);
}
@Test(expected = ArithmeticException.class)
public void whenDivideTwoInt_shouldThrowArithmeticExIfRoundNotDefinedButNeeded() {
IntMath.divide(10, 3, RoundingMode.UNNECESSARY);
}
2.5. factorial(int n)
计算阶乘 n!。当 n=0 返回 1;结果超出 int 范围时返回 Integer.MAX_VALUE
。
@Test
public void whenFactorialInt_shouldReturnTheResultIfInIntRange() {
int result = IntMath.factorial(5);
assertEquals(120, result);
}
@Test
public void whenFactorialInt_shouldReturnIntMaxIfNotInIntRange() {
int result = IntMath.factorial(Integer.MAX_VALUE);
assertEquals(Integer.MAX_VALUE, result);
}
2.6. floorPowerOfTwo(int x)
返回小于等于 x 的最大 2 的幂。例如 x=30 时返回 16(因为 2^4=16 < 30 < 32=2^5)
@Test
public void whenFloorPowerOfInt_shouldReturnValue() {
int result = IntMath.floorPowerOfTwo(30);
assertEquals(16, result);
}
2.7. gcd(int a, int b)
计算 a 和 b 的最大公约数(GCD)。
@Test
public void whenGcdOfTwoInt_shouldReturnValue() {
int result = IntMath.gcd(30, 40);
assertEquals(10, result);
}
2.8. isPowerOfTwo(int x)
判断 x 是否为 2 的幂。
@Test
public void givenIntOfPowerTwo_whenIsPowOfTwo_shouldReturnTrue() {
boolean result = IntMath.isPowerOfTwo(16);
assertTrue(result);
}
@Test
public void givenIntNotOfPowerTwo_whenIsPowOfTwo_shouldReturnFalse() {
boolean result = IntMath.isPowerOfTwo(20);
assertFalse(result);
}
2.9. isPrime(int n)
判断 n 是否为质数。
@Test
public void givenNonPrimeInt_whenIsPrime_shouldReturnFalse() {
boolean result = IntMath.isPrime(20);
assertFalse(result);
}
2.10. log10(int x, RoundingMode mode)
计算以 10 为底的对数,结果按指定模式舍入。
@Test
public void whenLog10Int_shouldReturnTheResultForCeilingRounding() {
int result = IntMath.log10(30, RoundingMode.CEILING);
assertEquals(2, result);
}
@Test(expected = ArithmeticException.class)
public void whenLog10Int_shouldThrowArithmeticExIfRoundNotDefinedButNeeded() {
IntMath.log10(30, RoundingMode.UNNECESSARY);
}
2.11. log2(int x, RoundingMode mode)
计算以 2 为底的对数,结果按指定模式舍入。
@Test
public void whenLog2Int_shouldReturnTheResultForCeilingRounding() {
int result = IntMath.log2(30, RoundingMode.CEILING);
assertEquals(5, result);
}
@Test(expected = ArithmeticException.class)
public void whenLog2Int_shouldThrowArithmeticExIfRoundNotDefinedButNeeded() {
IntMath.log2(30, RoundingMode.UNNECESSARY);
}
2.12. mean(int x, int y)
计算两个整数的平均值(避免溢出)。
@Test
public void whenMeanTwoInt_shouldReturnTheResult() {
int result = IntMath.mean(30, 20);
assertEquals(25, result);
}
2.13. mod(int x, int m)
计算 x 除以 m 的余数(取模运算)。
@Test
public void whenModTwoInt_shouldReturnTheResult() {
int result = IntMath.mod(30, 4);
assertEquals(2, result);
}
2.14. pow(int b, int k)
计算 b 的 k 次幂。
@Test
public void whenPowTwoInt_shouldReturnTheResult() {
int result = IntMath.pow(6, 4);
assertEquals(1296, result);
}
2.15. saturatedAdd(int a, int b) 及同类方法
饱和加法:溢出时返回 Integer.MAX_VALUE
,下溢时返回 Integer.MIN_VALUE
。同类方法包括:
saturatedMultiply
(乘法)saturatedPow
(幂运算)saturatedSubtract
(减法)
@Test
public void whenSaturatedAddTwoInt_shouldReturnTheResult() {
int result = IntMath.saturatedAdd(6, 4);
assertEquals(10, result);
}
@Test
public void whenSaturatedAddTwoInt_shouldReturnIntMaxIfOverflow() {
int result = IntMath.saturatedAdd(Integer.MAX_VALUE, 1000);
assertEquals(Integer.MAX_VALUE, result);
}
2.16. sqrt(int x, RoundingMode mode)
计算平方根,结果按指定模式舍入。
@Test
public void whenSqrtInt_shouldReturnTheResultForCeilingRounding() {
int result = IntMath.sqrt(30, RoundingMode.CEILING);
assertEquals(6, result);
}
@Test(expected = ArithmeticException.class)
public void whenSqrtInt_shouldThrowArithmeticExIfRoundNotDefinedButNeded() {
IntMath.sqrt(30, RoundingMode.UNNECESSARY);
}
3. LongMath 工具类
LongMath
提供与 IntMath
类似的功能,但针对 long 类型。以下是其特有方法:
3.1. mod(long x, int m) 和 mod(long x, long m)
计算 long 类型取模运算,支持 int 或 long 类型模数。
@Test
public void whenModLongAndInt_shouldModThemAndReturnTheResult() {
int result = LongMath.mod(30L, 4);
assertEquals(2, result);
}
@Test
public void whenModTwoLongValues_shouldModThemAndReturnTheResult() {
long result = LongMath.mod(30L, 4L);
assertEquals(2L, result);
}
4. BigIntegerMath 工具类
BigIntegerMath
处理大整数运算,方法与 IntMath
高度相似,但操作对象为 BigInteger
。核心方法包括:
- 二项式系数
- 阶乘
- 对数运算
- 平方根
- 最大公约数
⚠️ 注意:由于 BigInteger
本身不会溢出,因此无需 checked/saturated 系列方法。
5. DoubleMath 工具类
DoubleMath
专注于浮点数运算,提供以下特有方法:
5.1. isMathematicalInteger(double x)
判断 double 值是否可无损表示为整数(如 5.0 是,5.2 不是)。
@Test
public void givenInt_whenMathematicalDouble_shouldReturnTrue() {
boolean result = DoubleMath.isMathematicalInteger(5);
assertTrue(result);
}
@Test
public void givenDouble_whenMathematicalInt_shouldReturnFalse() {
boolean result = DoubleMath.isMathematicalInteger(5.2);
assertFalse(result);
}
5.2. log2(double x)
计算以 2 为底的对数。
@Test
public void whenLog2Double_shouldReturnResult() {
double result = DoubleMath.log2(4);
assertEquals(2, result, 0);
}
6. 总结
Guava 的数学工具类提供了:
✅ 类型安全:避免 int/long 运算溢出
✅ 精度控制:支持多种舍入模式
✅ 性能优化:如快速幂运算、质数检测
✅ 大数支持:通过 BigIntegerMath
处理超大数
这些工具类特别适合需要精确数学计算的场景,比如金融、密码学或科学计算。完整代码示例可在 GitHub 查看。