1. 概述

本文将介绍 Guava 库中实用的数学运算工具类。Guava 提供了四个核心数学工具类:

  1. IntMath - 处理 int 类型运算
  2. LongMath - 处理 long 类型运算
  3. BigIntegerMath - 处理 BigInteger 类型运算
  4. 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 查看。


原始标题:Guide to Mathematical Utilities in Guava

« 上一篇: Java字符串分割指南
» 下一篇: Java 序列化详解