这个包中含有各种各样的数学工具类,比 JDK 更优化, 测试更完善
IntMath
],[LongMath
], DoubleMath
], 和 [BigIntegerMath
], 这些类具有这相互平行的结构, com.google.common.primitives
包中, 有一些函数或者类可能看起来不那么的’数学’, Ints
].**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);
Apache Commons
的 MathUtils
互相媲美, IntMath.log2(x, CEILING)
在你进行快速浏览代码的时候也能清晰快速的了解它的含义, 32 - Integer.numberOfLeadingZeros(x - 1)
在你不查看API的情况下就很难理解 注意: 这些类与 GWT 不兼容的,他们也不都是 GWT 的优化, 原因是他们有不同的计算溢出逻辑。
对于整数, Math工具包主要处理三种整数类型值的计算: int
, long
, 和 BigInteger
。
其中的工具类被合理的命名为[IntMath
], [LongMath
], 和 [BigIntegerMath
].
Guava Math 为 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); // 抛出 ArithmeticException 异常.
IntMath
, LongMath
和 BigIntegerMath
提供了很多实数运算的方法, 但是他们都会将结果取整.
这些方法接受一个 [java.math.RoundingMode
] 枚举值用作取整的类型, 这枚举值和 JDK 中的 RoundingMode
相同,
并且遵循着以下规则:
DOWN
: 向下取整. (与Java除法的行为相同, 比如 Java 中计算 5 / 2 = 2.)UP
: 向上取整(即 5 / 2 = 3).FLOOR
: 向着0的负无穷的方向取整(实际检验中,此枚举类结果为 5 / 2 = 2,与 DOWN 相同,具体区别有待验证).CEILING
: 向着0的正无穷方向取整(实际检验中,此枚举类结果为 5 / 2 = 3,与 UP 相同,具体区别有待验证).UNNECESSARY
: 无需取整,若如此做,将会抛出一个 ArithmeticException
异常并快速失败.HALF_UP
: 四舍五入,0.5的话向前进1( 5 / 2 = 3).HALF_DOWN
: 特殊的四舍五入,大于0.5进1,等于小于0.5为0(5 / 2 = 2).HALF_EVEN
: 特殊的四舍五入,0.5会进位到最相邻的偶数,大于0.5则进位。 这些方法在被使用时应该是具有良好可读性的, 例如: divide(x, 3, CEILING)
的语义在快速通读浏览的情况下也是非常清晰的。
此外, 除了 sqrt
之外, 这些方法的内部采用整数计算进行实现,
而在 sqrt
中, 则是先构建构建初始近似值(先进行浮点数计算).
Operation | IntMath |
LongMath |
BigIntegerMath |
---|---|---|---|
Division | [divide(int, int, RoundingMode) ] |
[divide(long, long, RoundingMode) ] |
[divide(BigInteger, BigInteger, RoundingMode) ] |
Base-2 logarithm | [log2(int, RoundingMode) ] |
[log2(long, RoundingMode) ] |
[log2(BigInteger, RoundingMode) ] |
Base-10 logarithm | [log10(int, RoundingMode) ] |
[log10(long, RoundingMode) ] |
[log10(BigInteger, RoundingMode) ] |
Square root | [sqrt(int, RoundingMode) ] |
[sqrt(long, RoundingMode) ] |
[sqrt(BigInteger, RoundingMode) ] |
BigIntegerMath.sqrt(BigInteger.TEN.pow(99), RoundingMode.HALF_EVEN);
// returns 31622776601683793319988935444327185337195551393252
我们提供了一些额外的我们所发现的十分有用的一些数学方法(函数/工具/公式).
Operation 运算 | IntMath 整形计算 |
LongMath 长整型计算 |
BigIntegerMath 超大整形数据计算 |
---|---|---|---|
Greatest common divisor | [gcd(int, int) ] |
[gcd(long, long) ] |
In JDK: [BigInteger.gcd(BigInteger) ] |
Modulus (总是正值, -5 取模 3 返回 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 testing | [isPowerOfTwo(int) ] |
[isPowerOfTwo(long) ] |
[isPowerOfTwo(BigInteger) ] |
Factorial (如果输入过大, 则返回最大值 MAX_VALUE ) |
[factorial(int) ][IntMath.factorial(int) ] |
[factorial(int) ][LongMath.factorial(int) ] |
[factorial(int) ][BigIntegerMath.factorial(int) ] |
Binomial coefficient (如果值过大, 则返回最大值 MAX_VALUE ) |
[binomial(int, int) ][IntMath.binomial(int, int) ] |
[binomial(int, int) ][LongMath.binomial(int, int) ] |
[binomial(int, int) ][BigIntegerMath.binomial(int, int) ] |
Guava 对于浮点数计算的实现采用的完全是 JDK 中的方法, 但是在 Guava Math 中,
我们为 [DoubleMath
] 添加了一些十分有用的方法.
Method 方法 | Description 描述 |
---|---|
[isMathematicalInteger(double) ] |
判断这个数是一个有限数(非无穷)并且是一个精确的整数. |
[roundToInt(double, RoundingMode) ] |
围绕这个特殊的数, 将其转换成一个整形 int,如果溢出(超出int的范围)则抛出异常 |
[roundToLong(double, RoundingMode) ] |
围绕这个特殊的数, 将其转换为一个 long, 如果溢出, 则抛出异常. |
[roundToBigInteger(double, RoundingMode) ] |
将这个数转换为 BigInteger , 如果这个数是无限的, 则抛出异常. |
[log2(double, RoundingMode) ] |
取 2 的 log 对数, 并根据 RoundingMode 转换为 int; 比 JDK 中的 Math.log(double) 计算速度要快. |
后记:原文发布在 Github 上,欢迎 Stars~