数学:JDK未提供经过优化、全面测试的数学工具。
这个包com.google.common.math
包含各种数学工具。
1.内容
- 基本的独立数学函数根据所涉及的主要数字类型分为
IntMath
、LongMath
、DoubleMath
和BigIntegerMath
类。这些类具有并行结构,但每个类仅支持函数的相关子集。请注意,在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.整数类型的数学
这些工具主要处理三种整数类型:int
、long
和BigInteger
。这些类型的数学工具方便地命名为IntMath
、LongMath
和BigIntegerMath
。
4.1校验算法
我们为IntMath
和LongMath
提供了算术方法,这些方法在溢出时会快速失败,而不是无视它们。
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.实值方法
IntMath
、LongMath
和BigIntegerMath
支持多种具有“精确实值”的方法,但是会将其结果舍入为整数。这些方法接受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
的初始近似值外,这些函数中的每一个内部都仅使用整数运算。
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) 快。 |