数学(Math)
此包包含大量数学的实用工具。
内容
- 基本的独立的数学函数被分为基于原生数字类型所涉及的类
IntMath
,LongMath
,DoubleMath
和BigIntegerMath
。这些类存在平行结构,但是每一个只支持相关的子集函数。注意本质上不那么数学化的类似的函数可以在com.google.common.primitives
类中找,就像Ints
。 - 对于单个和成对的数据集,提供了大量统计计算(平均值,中位数等等)。通过阅读此概览开始,而不是仅仅浏览Javadoc。
LinearTransformation
表示形式为y = mx + b
的double
值的行内转换;例如,英尺和米之间的转换,或者开尔文和华氏度之间的转换。
示例
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);
为什么使用这些?
- 这些工具已经对异常溢出条件进行了彻底的测试。溢出语义(如果相关)已经在相关联的文档清晰的指定。当一个先决条件失败,它也快速失败。
- 他们已经进行了基准测试和优化。当然性能不可避免取决于特定的硬件细节会变化,他们的速度可以和Apache Commons的
MathUtils
做竞争,并且在某些情况还要优于他们。 - 他们设计于鼓励可读性,正确的编码习惯。
IntMath.log2(x, CEILING)
的含义是明确的,即使在偶然的通读中也是明显的。32 - Integer.numberOfLeadingZeros(x - 1)
的含义就不是那么明确。
注意:这些工具与GWT不是特别兼容,并不是对GWT的优化,由于是不同的溢出逻辑。
关于整型的数学(Math)
这些工具主要处理三种整型类型:int
,long
,BigInteger
。这些类型的数学工具合适地命名为IntMath
,LongMath
,BigIntegerMath
。
检查运算
我们提供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
实数方法
IntMath
,LongMath
和BigIntegerMath
对大量使用“精确实数”方法的支持,但是取舍(round)他们的结果为一个整型数。这些方法接收一个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
附加函数
我们发现几个其他有用的数学函数提供支持。
操作 | IntMath | LongMath | BigIntegerMath |
---|---|---|---|
最大公约数 | gcd(int, int) | gcd(long, long) | 在JDK中的BigInteger.gcd(BigInteger) |
模数(总是非负数,-5以3为模是1) | mod(int, int) | mod(long, long) | 在JDK中BigInteger.mod(BigInteger) |
乘方(可能溢出) | pow(int, int) | pow(long, int) | JDK中的BigInteger.pow(int) |
2的幂测试 | isPowerOfTwo(int) | isPowerOfTwo(long) | isPowerOfTwo(BigInteger) |
阶乘(如果输入太大返回MAX_VALUE ) | factorial(int) | factorial(int) | factorial(int) |
二项式系数 | 如果输入太大返回MAX_VALUE | binomial(int, int) | binomial(int, int) |
浮点运算
浮点运算已经完全被JDK涵盖了,但是我们添加了几个有用的方法到DoubleMath
。
方法 | 描述 |
---|---|
isMathematicalInteger(double) | 测试输入是否是有限的精确整数 |
roundToInt(double, RoundingMode) | 取舍指定的数字并将它转换为一个整型,如果它适合整型,否则快速失败 |
roundToLong(double, RoundingMode) | 取舍指定的数字并将它转换为一个长整型,如果它适合长整型,否则快速失败 |
roundToBigInteger(double, RoundingMode) | 取舍指定的数字并将它转换为一个BigInteger ,如果它适合,否则快速失败 |
log2(double, RoundingMode) | 使用基于2为底的对数,并使用指定的RoundingMode 取舍为一个int 。比Math.log(double) 快 |