内容

  • 基本的独立数学函数根据涉及的主要数字类型分为IntMathLongMathDoubleMathBigIntegerMath。这些类具有并行结构,但每个类只支持函数的相关子集。请注意,在com.google.common.primitives类中也可以找到类似的函数,它们本质上不那么数学化。
  • 为单个和成对的数据集提供了各种统计计算(平均值、中位数等)。从阅读本文开始,而不仅仅是浏览Javadoc。
  • LinearTransformation 表示 y = mx + b的两个值之间的线性变换; 例如,英尺和米之间的换算,或者凯尔文和摄氏温度之间的换算。

示例:

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);

为什么使用Guava Math

  • Guava Math针对各种不常见的溢出情况都有充分的测试;对溢出语义,Guava文档也有相应的说明;如果运算的溢出检查不能通过,将导致快速失败;
  • Guava Math的性能经过了精心的设计和调优;虽然性能不可避免地依据具体硬件细节而有所差异,但Guava Math的速度通常可以与Apache Commons 的MathUtils相比,在某些场景下甚至还有显著提升;
  • Guava Math在设计上考虑了可读性和正确的编程习惯;IntMath.log2(x, CEILING)所表达的含义,即使在快速阅读时也是清晰明确的。而 32-Integer.numberOfLeadingZeros(x – 1)对于阅读者来说则不够清晰。
注意:Guava Math和GWT格外不兼容,这是因为Java和Java Script语言的运算溢出逻辑不一样。

整数运算

Guava Math主要处理三种整数类型:intlongBigInteger。这三种类型的运算工具类分别叫做IntMathLongMathBigIntegerMath

有溢出检查的运算

Guava Math提供了若干有溢出检查的运算方法:结果溢出时,这些方法将快速失败而不是忽略溢出

IntMathLongMath
IntMath.checkedAddLongMath.checkedAdd
IntMath.checkedSubtractLongMath.checkedSubtract
IntMath.checkedMultiplyLongMath.checkedMultiply
IntMath.checkedPowLongMath.checkedPow
IntMath.checkedAdd(Integer.MAX_VALUE, Integer.MAX_VALUE); // throws ArithmeticException

实数运算

IntMathLongMathBigIntegerMath提供了很多实数运算的方法,并把最终运算结果舍入成整数。这些方法接受一个 java.math.RoundingMode枚举值作为舍入的模式:

  • DOWN:向零方向舍入(去尾法)
  • UP:远离零方向舍入
  • FLOOR:向负无限大方向舍入
  • CEILING:向正无限大方向舍入
  • UNNECESSARY:不需要舍入,如果用此模式进行舍入,应直接抛出 ArithmeticException
  • HALF_UP:向最近的整数舍入,其中 x.5 远离零方向舍入
  • HALF_DOWN:向最近的整数舍入,其中 x.5 向零方向舍入
  • HALF_EVEN:向最近的整数舍入,其中 x.5 向相邻的偶数舍入

这些方法旨在提高代码的可读性,例如,divide(x, 3, CEILING)即使在快速阅读时也是清晰。此外,这些方法内部采用构建整数近似值再计算的实现,除了在构建sqrt(平方根)运算的初始近似值时有浮点运算,其他方法的运算全过程都是整数或位运算,因此性能上更好。

OperationIntMathLongMathBigIntegerMath
Divisiondivide(int, int, RoundingMode)divide(long, long, RoundingMode)divide(BigInteger, BigInteger, RoundingMode)
Base-2 logarithmlog2(int, RoundingMode)log2(long, RoundingMode)log2(BigInteger, RoundingMode)
Base-10 logarithmlog10(int, RoundingMode)log10(long, RoundingMode)log10(BigInteger, RoundingMode)
Square rootsqrt(int, RoundingMode)sqrt(long, RoundingMode)sqrt(BigInteger, RoundingMode)
BigIntegerMath.sqrt(BigInteger.TEN.pow(99), RoundingMode.HALF_EVEN);
   // returns 31622776601683793319988935444327185337195551393252

附加功能

Guava还另外提供了一些有用的运算函数

OperationIntMathLongMathBigIntegerMath
Greatest common divisorgcd(int, int)gcd(long, long)In JDK: BigInteger.gcd(BigInteger)
Modulus (always nonnegative, -5 mod 3 is 1)mod(int, int)mod(long, long)In JDK: BigInteger.mod(BigInteger)
Exponentiation (may overflow)pow(int, int)pow(long, int)In JDK: BigInteger.pow(int)
Power-of-two testingisPowerOfTwo(int)isPowerOfTwo(long)isPowerOfTwo(BigInteger)
Factorial (returns MAX_VALUE if input too big)factorial(int)factorial(int)factorial(int)
Binomial coefficient (returns MAX_VALUE if too big)binomial(int, int)binomial(int, int)binomial(int, int)

浮点数运算

JDK比较彻底地涵盖了浮点数运算,但Guava在DoubleMath类中也提供了一些有用的方法。

MethodDescription
isMathematicalInteger(double)判断该浮点数是不是一个整数
roundToInt(double, RoundingMode)舍入为int;对无限小数、溢出抛出异常
roundToLong(double, RoundingMode)舍入为long;对无限小数、溢出抛出异常
roundToBigInteger(double, RoundingMode)舍入为BigInteger;对无限小数抛出异常
log2(double, RoundingMode)2的浮点对数,并且舍入为int,比JDK的Math.log(double)更快

【腾讯云】境外1核2G服务器低至2折,半价续费券限量免费领取!
https://cloud.tencent.com/act/cps/redirect?redirect=1068&cps_key=e4b50f6c64a4480367f8a8d16fd07c5a&from=console

标签: Guava, 数学运算, LongMath, DoubleMath

添加新评论