BigDecimal是不可變的、任意精度的、有符號的、十進制數.
組成部分
| BigDecimal 由任意精度的整數非標度值 和 32 位的整數標度 (scale) 組成 |
|
BigDecimal 表示的數值是 :
unscaledValue × 10的-scale 次冪
|
私有成員intVal就是非標度值
scale就是標度
標度
BigDecimal由非標度值 和 32 位的整數標度 (scale) 組成
BigDecimal表示的數為: unscaledValue × 10的-scale 次冪
顯然
如果scale為零或正數,最終的結果中,小數點后面的位數就等於scale標度
比如: scale為1 10的-1次方, 0.1 小數點后有1位
如果 scale 是負數,那最終的結果將會是乘以 10的|scale| 次方
比如: scale為-3 最終的值就是非標度值乘以 1000 ( 10的(- -3)次方 )
精度
非標度值的數字個數
構造方法
幾個關鍵概念 非標度值 標度 運算規則
構造方法就是圍繞這幾個點展開的
| BigDecimal(BigInteger val) | 將 BigInteger 轉換為 BigDecimal |
|
BigDecimal(BigInteger unscaledVal,int scale)
|
將 BigInteger 非標度值和 int 標度轉換為 BigDecimal |
|
BigDecimal(BigInteger unscaledVal,
int scale,
MathContext mc)
|
將 BigInteger 非標度值和 int 標度轉換為 BigDecimal
(根據上下文設置進行舍入)
|
|
BigDecimal(BigInteger val,MathContext mc)
|
將 BigInteger 轉換為 BigDecimal(根據上下文設置進行舍入) |
| BigDecimal(int val) | int 轉換為 BigDecimal |
| BigDecimal(int val, MathContext mc) | int 轉換為 BigDecimal 根據上下文設置進行舍入 |
| BigDecimal(long val) | long 轉換為 BigDecimal |
| BigDecimal(long val, MathContext mc) | long 轉換為 BigDecimal 根據上下文設置進行舍入 |
| BigDecimal(double val) | double 轉換為 BigDecimal |
| BigDecimal(double val, MathContext mc) | double 轉換為 BigDecimal 根據上下文設置進行舍入 |
構造方法注意事項
BigDecimal(double val)
BigDecimal(double val, MathContext mc)
這兩個構造方法具有一定的不確定性
如下圖所示,這是因為在二進制中無法准確地表示0.1 如同十進制無法准確表示 1/3 一樣
當 double 必須用作 BigDecimal 的源時
請注意,此構造方法public BigDecimal(double val)提供了一個准確轉換;
它不等同於下面的操作:
先使用 Double.toString(double) 方法,
然后使用 BigDecimal(String) 構造方法
要獲取該結果,請使用 static valueOf(double) 方法
String構造方法的格式
| Sign(可選) Significand Exponent opt(可選) |
|
Sign 符號:
+
-
Significand 有效數字至少要有整數或者小數的一位數字:
IntegerPart .FractionPart 整數和小數
. FractionPart 小數
IntegerPart 整數
IntegerPart:
Digits
FractionPart:
Digits
Exponent: 指數部分
ExponentIndicator SignedInteger
ExponentIndicator: 指數符號
e
E
SignedInteger: 有符號數
Sign(可選的) Digits
Digits:
Digit
Digits Digit
Digit:
Character.isDigit(char) 對其返回 true 的任何字符,如 0、1、2……
|
| -1.23E-12 這是一個完整的格式 含有符號 / 含有整數部分 / 含有小數部分 /含有指數部分/指數部分含有符號 |
除非有必要
否則在你需要 將 float 或 double 轉換為 BigDecimal時
首選BigDecimal(String val)
構造方法與 Float.toString(float) 和 Double.toString(double) 返回的值兼容
它不會遇到 BigDecimal(double) 構造方法的不可預知問題
常量
內部定義了幾個public final static int的常量,用於標注舍入模式
與RoundingMode中是一一對應的,這幾個不要再使用了
請使用RoundingMode中的枚舉值
|
ROUND_UP
ROUND_DOWN
ROUND_CEILING
ROUND_FLOOR
ROUND_HALF_UP
ROUND_HALF_DOWN
ROUND_HALF_EVEN
ROUND_UNNECESSARY
|
另外還有三個常用對象
public static final BigDecimal ZERO
public static final BigDecimal ONE
public static final BigDecimal TEN
常用方法
屬性獲取
四則運算
| divideToIntegralValue(BigDecimal divisor) | 返回 BigDecimal 值為向下舍入所得商值 (this / divisor) 的整數部分 首選標度為 (this.scale() - divisor.scale()) |
| divideToIntegralValue(BigDecimal divisor, MathContext mc) | 返回 BigDecimal 其值為 (this / divisor) 的整數部分 准確商值的整數部分與舍入模式無關 所以舍入模式不影響此方法返回的值 首選標度是 (this.scale() - divisor.scale()) 如果准確商值的整數部分需要的位數多於 mc.precision 則拋出 ArithmeticException |
divideToIntegralValue 需要注意因為是取整數部分,所以舍入模式是不影響的
針對於參數MathContext 有影響的是精度
注意
如果同時需要整數商和余數
則divideAndRemainder比分別使用 divideToIntegralValue 和 remainder 方法更快速,因為相除僅需執行一次
remainder則是依賴於divideAndRemainder ,然后返回的第二個元素
數學方法
equals
|
判斷是否相等
與 compareTo 不同
僅當兩個 BigDecimal 對象的值和標度都相等時,此方法才認為它們相等
(因此通過此方法進行比較時,2.0 不等於 2.00)
|
一定要注意到compareTo方法與equals方法 對於相等的定義是不一致的
valueOf
setScale
setScale 系列並不是設置BigDecimal的scale BigDecimal是不可變得
setScale 是一個轉換器,將參數的BigDecimal轉換為指定標度的值
值本身不會變化,變化的是形式
返回的是一個新的BigDecimal,不過這個新的BigDecimal並不一定是新創建的
可能是使用緩存,新是相對於調用者來說
方法列表:
negate/plus/round
xxxValue
| intValue() 轉換為 int 丟棄此 BigDecimal 的小數部分 如果生成的 "BigInteger" 太大而不適合用 int 表示,則僅返回 32 位低位字節 此轉換會丟失關於此 BigDecimal 值的總大小和精度的信息 |
|
longValue()
轉換為 long
丟棄此 BigDecimal 的小數部分
如果生成的 "BigInteger" 太大
僅返回 64 位低位字節
此轉換會丟失關於此 BigDecimal 值的總大小和精度的信息
|
| floatValue() 轉換為 float 如果BigDecimal 的值太大而不能表示為 float 將其適當地轉換為 Float.NEGATIVE_INFINITY 或 Float.POSITIVE_INFINITY 此轉換也可能丟失關於 BigDecimal 值精度的信息 |
| doubleValue() 轉換為 double 如果此 BigDecimal 的數量太大而不能表示為 double 將其適當地轉換為 Double.NEGATIVE_INFINITY 或 Double.POSITIVE_INFINITY 轉換也可能丟失關於 BigDecimal 值精度的信息 |
| BigInteger toBigInteger() 轉換為 BigInteger 丟棄此 BigDecimal 的小數部分 此轉換會丟失關於 BigDecimal 值的精度信息 |
XXXValueExact
exact版本的區別就在於是否能夠准確轉換,否則拋出異常
也就是他要么返回一個准確地值要么就拋出異常
hashCode
| int hashCode() |
| 返回此 BigDecimal 的哈希碼 數值上相等但標度不同的兩個 BigDecimal 對象(如,2.0 和 2.00)通常沒有 相同的哈希碼 |
toString
|
toString() 返回字符串表示形式,如果需要指數,則使用科學記數法
toEngineeringString() 返回字符串表示形式,需要指數時,則使用工程計數法
toPlainString() 返回不帶指數字段的此 BigDecimal 的字符串表示形式
|
| toString的三個方法根本邏輯是一樣的,都是轉換為字符串 只不過具體的形式不同 |
ulp
unit in the last place
兩個數之間的距離,在數學中是無限的,比如1和2之間有無數個數
但是在計算機中是有限的,因為計算機需要用有限個字節來表示double或者float,計算機表示不了無限的數
因為沒有無限內存
假設兩個數之間有10個數,那么ulp 就是1/10
1和2之間有一個數 距離為1
1.1和2.1之間有十個數 距離為0.1
這就是ulp
非零 BigDecimal 值的 ulp 是此值與下一個具有相同位數的較大 BigDecimal 值之間的正距離
零值的 ulp 在數值上等於1 和 this.scale()之間的距離
所以可以說所有的數的ulp為[1, this.scale()]
移動小數點
| movePointLeft 該值的小數點向左移動 n 位 如果 n 為負數,則該調用等效於 movePointRight(-n) 如果 n 為非負數,則調用僅將 n 添加到該標度 返回的值和標度分別為: |
| movePointRight 小數點向右移動 n 位 如果 n 為負,則該調用等效於 movePointLeft(-n) 如果 n 為非負數,則該調用僅從該標度減去 n 返回的值和標度分別為: ![]() |
| BigDecimal stripTrailingZeros() 形式轉換,數值是相等的 轉換為去掉所有尾部的0的形式的數值 800.000去掉所有的0 就是8 准換后為8乘以10的平方 |
總結
BigDecimal雖然有諸多特性與特別,,但是本質仍舊是浮點數
所以自然提供了浮點數相關的一些操作
作為數值的基本運算方法都具備的
需要注意的是構造方法之間的區別
除非特別需要,否則不要直接使用double構造
盡可能的使用String的形式
對於valueOf方法也是具有緩存的
BigDecimal是不可變的
setScale的名字起的不太規范,容易讓人迷惑,使用時要注意。




























