數學: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) 快。 |