Guava指南個人翻譯——Math

Math – Guava的數學工具包

這個包中含有各種各樣的數學工具類,比 JDK 更優化, 測試更完善

Contents 綜述

  • Guava Math 提供了爲基本數據類型而設計的獨立的類[IntMath],[LongMath],
    [DoubleMath], 和 [BigIntegerMath], 這些類具有這相互平行的結構,
    他們的方法都是基於相應數據類型而進行實現.
    **請注意: 在com.google.common.primitives包中, 有一些函數或者類可能看起來不那麼的’數學’,
    比如 [Ints].**
  • Guava 爲單個或者成對的數據集提供了各種統計計算的方法(比如求平均值,中位數等等).
    如果想使用 Guava Math 包,請先閱讀這個指南Stats 而不是去閱讀 Java DOC.
  • [LinearTransformation] 代表着 y = mx + b(這是個一次函數) 中的線性變換;
    比如英尺和米之間的換算(英尺 = 米 * 3.2808399 ), 或者開氏溫度與華氏溫度之間的換算(℉ = 1.8 * K - 459.67 ).

Examples 舉個栗子

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

Why use these? 爲什麼使用這些工具類?

  • Guava Math的工具類爲很多不常見的溢出情況都做了充分的測試. 溢出的語義也在相關的文檔中進行了清晰的定義.
    如果預檢查不能通過, 則快速的返回失敗(異常).
  • Guava Math 已經進行了基準測試和最佳的優化, 儘管因爲不同的硬件原因會造成不可避免的性能差異,
    但是 Guava Math 通常情況下的運行速度與 Apache CommonsMathUtils 互相媲美,
    在某些場景下, Guava Math 甚至更優.
  • 這些類在設計之初就考慮到了代碼的可讀性、幫助養成好的編碼習慣。
    比如 IntMath.log2(x, CEILING) 在你進行快速瀏覽代碼的時候也能清晰快速的瞭解它的含義,
    32 - Integer.numberOfLeadingZeros(x - 1) 在你不查看API的情況下就很難理解
    (而它,實際上表示x-1轉換爲32位二進制補碼之後,最高有值位前0的個數)。

注意: 這些類與 GWT 不兼容的,他們也不都是 GWT 的優化, 原因是他們有不同的計算溢出邏輯。

Math on Integral Types 整型數值計算

對於整數, Math工具包主要處理三種整數類型值的計算: int, long, 和 BigInteger
其中的工具類被合理的命名爲[IntMath], [LongMath], 和 [BigIntegerMath].

Checked Arithmetic 檢查方法

Guava Math 爲 IntMathLongMath 計算中可能的一些結果溢出情況提供了一些運算方法,
這些方法將導致有結果溢出的計算 快速失敗 而不是忽略掉溢出。

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 異常.

Real-valued methods 實數運算

IntMath, LongMathBigIntegerMath 提供了很多實數運算的方法, 但是他們都會將結果取整.
這些方法接受一個 [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則進位。
    (_注:HALF_EVEN:我們用 12 與 13 除以 5 舉例, 12 / 5 = 2.5 那麼 HALF_EVEN 返回的就是 2, 13 / 5 = 2.6 那麼 HALF_EVEN 返回 3.
    特殊的: 21 / 6 = 3.5 進位到最相鄰的偶數,那麼返回 4_)。

這些方法在被使用時應該是具有良好可讀性的, 例如: 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

Additional functions 其他方法

我們提供了一些額外的我們所發現的十分有用的一些數學方法(函數/工具/公式).

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

Floating-point arithmetic 浮點數方法

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~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章