# 12-数学运算
[原文链接](http://code.google.com/p/guava-libraries/wiki/MathExplained) [译文链接](http://ifeve.com/google-guava-math) **译者:**沈义扬
## 范例
```
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);
```
## 为什么使用Guava Math
* Guava Math针对各种不常见的溢出情况都有充分的测试;对溢出语义,Guava文档也有相应的说明;如果运算的溢出检查不能通过,将导致快速失败;
* Guava Math的性能经过了精心的设计和调优;虽然性能不可避免地依据具体硬件细节而有所差异,但Guava Math的速度通常可以与Apache Commons的MathUtils相比,在某些场景下甚至还有显著提升;
* Guava Math在设计上考虑了可读性和正确的编程习惯;IntMath.log2(x, CEILING) 所表达的含义,即使在快速阅读时也是清晰明确的。而32-Integer.numberOfLeadingZeros(x – 1)对于阅读者来说则不够清晰。
_注意:Guava Math和GWT格外不兼容,这是因为Java和Java Script语言的运算溢出逻辑不一样。_
## 整数运算
Guava Math主要处理三种整数类型:int、long和BigInteger。这三种类型的运算工具类分别叫做[IntMath](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/IntMath.html)、[LongMath](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/LongMath.html)和[BigIntegerMath](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/BigIntegerMath.html)。
### 有溢出检查的运算
Guava Math提供了若干有溢出检查的运算方法:结果溢出时,这些方法将快速失败而不是忽略溢出
| [`IntMath.checkedAdd`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/IntMath.html#checkedAdd%28int, int%29) | [`LongMath.checkedAdd`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/LongMath.html#checkedAdd%28long, long%29) |
|:--- |:--- |:--- |:--- |
| [`IntMath.checkedSubtract`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/IntMath.html#checkedSubtract%28int, int%29) | [`LongMath.checkedSubtract`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/LongMath.html#checkedSubtract%28long, long%29) |
| [`IntMath.checkedMultiply`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/IntMath.html#checkedMultiply%28int, int%29) | [`LongMath.checkedMultiply`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/LongMath.html#checkedMultiply%28long, long%29) |
| [`IntMath.checkedPow`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/IntMath.html#checkedPow%28int, int%29) | [`LongMath.checkedPow`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/LongMath.html#checkedPow%28long, long%29) |
```
IntMath.checkedAdd(Integer.MAX_VALUE, Integer.MAX_VALUE); // throws ArithmeticException
```
## 实数运算
IntMath、LongMath和BigIntegerMath提供了很多实数运算的方法,并把最终运算结果舍入成整数。这些方法接受一个[java.math.RoundingMode](http://docs.oracle.com/javase/7/docs/api/java/math/RoundingMode.html)枚举值作为舍入的模式:
* DOWN:向零方向舍入(去尾法)
* UP:远离零方向舍入
* FLOOR:向负无限大方向舍入
* CEILING:向正无限大方向舍入
* UNNECESSARY:不需要舍入,如果用此模式进行舍入,应直接抛出ArithmeticException
* HALF_UP:向最近的整数舍入,其中x.5远离零方向舍入
* HALF_DOWN:向最近的整数舍入,其中x.5向零方向舍入
* HALF_EVEN:向最近的整数舍入,其中x.5向相邻的偶数舍入
这些方法旨在提高代码的可读性,例如,divide(x, 3, CEILING) 即使在快速阅读时也是清晰。此外,这些方法内部采用构建整数近似值再计算的实现,除了在构建sqrt(平方根)运算的初始近似值时有浮点运算,其他方法的运算全过程都是整数或位运算,因此性能上更好。
| **运算** | **IntMath** | **LongMath** | **BigIntegerMath** |
|:--- |:--- |:--- |:--- |
| 除法 | [`divide(int, int, RoundingMode)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/IntMath.html#divide%28int, int, java.math.RoundingMode%29) | [`divide(long, long, RoundingMode)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/LongMath.html#divide%28long, long, java.math.RoundingMode%29) | [`divide(BigInteger, BigInteger, RoundingMode)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/BigIntegerMath.html#divide%28java.math.BigInteger, java.math.BigInteger, java.math.RoundingMode%29) |
| 2为底的对数 | [`log2(int, RoundingMode)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/IntMath.html#log2%28int, java.math.RoundingMode%29) | [`log2(long, RoundingMode)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/LongMath.html#log2%28long, java.math.RoundingMode%29) | [`log2(BigInteger, RoundingMode)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/BigIntegerMath.html#log2%28java.math.BigInteger, java.math.RoundingMode%29) |
| 10为底的对数 | [`log10(int, RoundingMode)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/IntMath.html#log10%28int, java.math.RoundingMode%29) | [`log10(long, RoundingMode)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/LongMath.html#log10%28long, java.math.RoundingMode%29) | [`log10(BigInteger, RoundingMode)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/BigIntegerMath.html#log10%28java.math.BigInteger, java.math.RoundingMode%29) |
| 平方根 | [`sqrt(int, RoundingMode)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/IntMath.html#sqrt%28int, java.math.RoundingMode%29) | [`sqrt(long, RoundingMode)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/LongMath.html#sqrt%28long, java.math.RoundingMode%29) | [`sqrt(BigInteger, RoundingMode)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/BigIntegerMath.html#sqrt%28java.math.BigInteger, java.math.RoundingMode%29) |
```
// returns 31622776601683793319988935444327185337195551393252
BigIntegerMath.sqrt(BigInteger.TEN.pow(99), RoundingMode.HALF_EVEN);
```
### 附加功能
Guava还另外提供了一些有用的运算函数
| **运算** | **IntMath** | **LongMath** | **BigIntegerMath******* |
|:--- |:--- |:--- |:--- |
| 最大公约数 | [`gcd(int, int)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/IntMath.html#gcd%28int, int%29) | [`gcd(long, long)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/LongMath.html#gcd%28long, long%29) | [`BigInteger.gcd(BigInteger)`](http://docs.oracle.com/javase/6/docs/api/java/math/BigInteger.html#gcd%28java.math.BigInteger%29) |
| 取模 | [`mod(int, int)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/IntMath.html#mod%28int, int%29) | [`mod(long, long)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/LongMath.html#mod%28long, long%29) | [`BigInteger.mod(BigInteger)`](http://docs.oracle.com/javase/6/docs/api/java/math/BigInteger.html#mod%28java.math.BigInteger%29) |
| 取幂 | [`pow(int, int)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/IntMath.html#pow%28int, int%29) | [`pow(long, int)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/LongMath.html#pow%28long, int%29) | [`BigInteger.pow(int)`](http://docs.oracle.com/javase/6/docs/api/java/math/BigInteger.html#pow%28int%29) |
| 是否2的幂 | [`isPowerOfTwo(int)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/IntMath.html#isPowerOfTwo%28int%29) | [`isPowerOfTwo(long)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/LongMath.html#isPowerOfTwo%28long%29) | [`isPowerOfTwo(BigInteger)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/BigIntegerMath.html#isPowerOfTwo%28java.math.BigInteger%29) |
| 阶乘* | [`factorial(int)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/IntMath.html#factorial%28int%29) | [`factorial(int)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/LongMath.html#factorial%28int%29) | [`factorial(int)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/BigIntegerMath.html#factorial%28int%29) |
| 二项式系数* | [`binomial(int, int)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/IntMath.html#binomial%28int, int%29) | [`binomial(int, int)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/LongMath.html#binomial%28int, int%29) | [`binomial(int, int)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/BigIntegerMath.html#binomial%28int, int%29) |
*BigInteger的最大公约数和取模运算由JDK提供
*阶乘和二项式系数的运算结果如果溢出,则返回MAX_VALUE
## 浮点数运算
JDK比较彻底地涵盖了浮点数运算,但Guava在[DoubleMath](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/DoubleMath.html)类中也提供了一些有用的方法。
| [`isMathematicalInteger(double)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/DoubleMath.html#isMathematicalInteger%28double%29) | 判断该浮点数是不是一个整数 |
|:--- |:--- |
| [`roundToInt(double, RoundingMode)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/DoubleMath.html#roundToInt%28double, java.math.RoundingMode%29) | 舍入为int;对无限小数、溢出抛出异常 |
| [`roundToLong(double, RoundingMode)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/DoubleMath.html#roundToLong%28double, java.math.RoundingMode%29) | 舍入为long;对无限小数、溢出抛出异常 |
| [`roundToBigInteger(double, RoundingMode)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/DoubleMath.html#roundToBigInteger%28double, java.math.RoundingMode%29) | 舍入为BigInteger;对无限小数抛出异常 |
| [`log2(double, RoundingMode)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/math/DoubleMath.html#log2%28double, java.math.RoundingMode%29) | 2的浮点对数,并且舍入为int,比JDK的Math.log(double) 更快 |
- Google Guava官方教程(中文版)
- 1-基本工具
- 1.1-使用和避免null
- 1.2-前置条件
- 1.3-常见Object方法
- 1.4-排序: Guava强大的”流畅风格比较器”
- 1.5-Throwables:简化异常和错误的传播与检查
- 2-集合
- 2.1-不可变集合
- 2.2-新集合类型
- 2.3-强大的集合工具类:java.util.Collections中未包含的集合工具
- 2.4-集合扩展工具类
- 3-缓存
- 4-函数式编程
- 5-并发
- 5.1-google Guava包的ListenableFuture解析
- 5.2-Google-Guava Concurrent包里的Service框架浅析
- 6-字符串处理:分割,连接,填充
- 7-原生类型
- 9-I/O
- 10-散列
- 11-事件总线
- 12-数学运算
- 13-反射