Google Guava与数学运算相关的类

数学:JDK未提供经过优化、全面测试的数学工具。

这个包com.google.common.math包含各种数学工具。

1.内容

  • 基本的独立数学函数根据所涉及的主要数字类型分为IntMathLongMathDoubleMathBigIntegerMath类。这些类具有并行结构,但每个类仅支持函数的相关子集。请注意,在com.google.common.primitives类(例如Ints)中可能会找到本质上数学性较低的类似函数。
  • 对於单个和成对的数据集,都提供了各种统计计算(平均值、中位数等)。从阅读本概述开始,而不只是浏览Javadoc。
  • LinearTransformation表示形式y = mx + b的双精度值之间的线性转换;例如,英尺和米之间的转换,或者开氏温度与华氏度之间的转换。

2.示例

int logFloor = LongMath.log2(n, FLOOR);

int mustNotOverflow = IntMath.checkedMultiply(x, y);

long quotient = LongMath.divide(knownMultipleOfThree, 3, RoundingMode.UNNECESSARY); // fail fast on non-multiple of 3

BigInteger nearestInteger = DoubleMath.roundToBigInteger(d, RoundingMode.HALF_EVEN);

BigInteger sideLength = BigIntegerMath.sqrt(area, CEILING);

3.为什么要使用这些?

  • 这些工具已经针对异常的溢出条件进行了详尽的测试。在关联文档中已明确地指定了溢出语义(如果相关)。当前置条件失败时,它会快速失败。
  • 它们经过了基准测试和优化。虽然性能不可避免地取决于特定的硬件细节,但它们的速度与Apache Commons MathUtils中的类似函数相比——在某些情况下,甚至要好得多。
  • 它们被设计用来鼓励可读的、正确的编程习惯。IntMath.log2(x, CEILING)的含义是明确的,即使是随意通读也是显而易见的。 32 - Integer.numberOfLeadingZeros(x - 1)的含义不是。

注意这些工具与GWT并不是特别兼容,由于溢出逻辑不同,它们也没有针对GWT进行优化

4.整数类型的数学

这些工具主要处理三种整数类型:intlongBigInteger。这些类型的数学工具方便地命名为IntMathLongMathBigIntegerMath

4.1校验算法

我们为IntMathLongMath提供了算术方法,这些方法在溢出时会快速失败,而不是无视它们。

IntMath LongMath
IntMath.checkedAdd LongMath.checkedAdd
IntMath.checkedSubtract LongMath.checkedSubtract
IntMath.checkedMultiply LongMath.checkedMultiply
IntMath.checkedPow LongMath.checkedPow
IntMath.checkedAdd(Integer.MAX_VALUE, Integer.MAX_VALUE); // throws ArithmeticException

5.实值方法

IntMathLongMathBigIntegerMath支持多种具有“精确实值”的方法,但是会将其结果舍入为整数。这些方法接受java.math.RoundingMode。这与JDK中使用的RoundingMode相同,并且是一个具有以下值的枚举:

  • DOWN:向0方向舍入。(这是Java除法的行为)
  • UP:向远离0方向舍入。
  • FLOOR:向负无穷大方向舍入。
  • CEILING:向正无穷大方向舍入。
  • UNNECESSARY:不需要四舍五入;如果是,则通过抛出ArithmeticException快速失败。
  • HALF_UP:舍入到最接近的一半,将x.5向远离0方向舍入。
  • HALF_DOWN:舍入到最接近的一半,将x.5向0方向舍入。
  • HALF_EVEN:舍入到最接近的一半,将x.5向最接近的相邻偶数方向舍入。

这些方法在使用时具有可读性:例如,即使是随意的通读,divide(x, 3, CEILING)也是完全明确的。

此外,除了构造用于sqrt的初始近似值外,这些函数中的每一个内部都仅使用整数运算。

操作 IntMath LongMath BigIntegerMath
除法 divide(int, int, RoundingMode) divide(long, long, RoundingMode) divide(BigInteger, BigInteger, RoundingMode)
以2为底的对数 log2(int, RoundingMode) log2(long, RoundingMode) log2(BigInteger, RoundingMode)
以10为底的对数 log10(int, RoundingMode) log10(long, RoundingMode) log10(BigInteger, RoundingMode)
平方根 sqrt(int, RoundingMode) sqrt(long, RoundingMode) sqrt(BigInteger, RoundingMode)
BigIntegerMath.sqrt(BigInteger.TEN.pow(99), RoundingMode.HALF_EVEN);
   // returns 31622776601683793319988935444327185337195551393252

5.1附加功能

我们为发现有用的其他一些数学函数提供了支持。

操作 IntMath LongMath BigIntegerMath
最大公约数 gcd(int, int) gcd(long, long) In JDK: BigInteger.gcd(BigInteger)
取模数(总是非负的,-5 mod 3为1) mod(int, int) mod(long, long) In JDK: BigInteger.mod(BigInteger)
求幂(可能会溢出) pow(int, int) pow(long, int) In JDK: BigInteger.pow(int)
二次幂测试 isPowerOfTwo(int) isPowerOfTwo(long) isPowerOfTwo(BigInteger)
阶乘(如果输入太大,则返回MAX_VALUE factorial(int) factorial(int) factorial(int)
二项式系数(如果太大,则返回MAX_VALUE binomial(int, int) binomial(int, int) binomial(int, int)

6.浮点运算

JDK完全涵盖了浮点算法,但是我们向DoubleMath添加了一些有用的方法。

方法 描述
isMathematicalInteger(double) 测试输入是否是有限的和精确的整数。
roundToInt(double, RoundingMode) 将指定的数字舍入并将其强制转换为整数(如果它适合整数),否则将快速失败。
roundToLong(double, RoundingMode) 将指定的数字舍入并将其强制转换为长整数(如果它适合长整数),否则将快速失败。
roundToBigInteger(double, RoundingMode) 将指定数字舍入到BigInteger(如果有限),否则快速失败。
log2(double, RoundingMode) 以2为底的对数,并使用指定的RoundingMode舍入为一个int整数。比Math.log(double)快。

本文参考:
MathExplained
guava-tests-math

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章