public static void main(String[] args) { double value = 0.05 + 0.01; System.out.println(value); //0.060000000000000005 }
double 類型的 0.05 + 0.01 的結果咱們猜測的應該是 0.06
可是程序的數據結果倒是大大的超出了咱們的預料(咱們稱這種現象爲精度丟失
),形成上面的這種狀況的緣由是小數在計算機中的存儲形式形成的。html
精度丟失的緣由不是本篇博客的主要內容,因此在這裏再也不贅述,想要了解的能夠查看,文章頂部的 IEEE 754 的規範。java
double 類型存在着上面的這種問題,因此咱們確定是不能用它來進行特別精細的計算了,好比 科學研究
和 金融
相關的業務邏輯。由於一旦數據不精確就可能形成比較嚴重的問題。api
既然出現了上面的這種問題,確定是有解決辦法的,官方提供的解決辦法就是 BigDecimal
類。oracle
與BigDecimal相似的還有BigInteger
類.ide
具備char[]參數的構造方法咱們通常是不會去主動調用的,由於當咱們調用具備string參數的構造函數時,會間接地調用char[]參數的構造方法。函數
public BigDecimal(String val) { this(val.toCharArray(), 0, val.length()); }
在構建BigDecimal的時候推薦使用String參數的構造方法,由於double參數的構造方法會會出現一些問題。this
public static void main(String[] args) { BigDecimal bigDecimal = new BigDecimal(0.06); System.out.println(bigDecimal); BigDecimal bigDecimalStr = new BigDecimal("0.06"); System.out.println(bigDecimalStr); }
輸出結果以下code
0.059999999999999997779553950749686919152736663818359375 0.06
經過輸出結果咱們發現,當經過double參數的構造方法的來建立BigDecimal對象的時候,輸出結果更加的讓人頭大了 😠。形成這樣的狀況的緣由是:htm
官方文檔提到了像 0.一、0.06 這樣的double類型的數,不是一個精確的數值,因此形成了上面的這種狀況。而官方文檔也推薦了使用string參數的構造方法來構造 BigDecimal對象來避免這種問題。對象
public static void main(String[] args) { BigDecimal bd1 = new BigDecimal("0.5"); BigDecimal bdResult = bd1.add(new BigDecimal("0.1")); System.out.println(bdResult.toString()); }
經過BigDecimal咱們就能夠避免掉,精度就是形成的數據錯誤達的問題了,然而BigDecimal不單單能夠用來解決精度就是的問題,double類型能夠作到的BigDecimal類型一樣能夠作到(如:四則運算);而BigDecimal能夠進行精度的舍入(保留兩位小數等)功能則是double 類型作不具有的。
運算 | 方法 |
---|---|
加法 | bd1.add |
減法 | bd1.subtract |
乘法 | bd1.multiply |
除法 | bd1.divide |
取模/取餘數 | bd1.remainder |
經過BigDecimal對象能夠實現比較大小和判斷是否相等的功能。
public static void main(String[] args) { BigDecimal bd1 = new BigDecimal("0.5"); System.out.println(bd1.compareTo(new BigDecimal("0.5"))); System.out.println(bd1.compareTo(new BigDecimal("0.1"))); System.out.println(bd1.compareTo(new BigDecimal("0.6"))); } /* 輸出結果: 0 1 -1 */
對精度的控制體如今保留小數上,咱們能夠經過BigDecimal.scale()方法來對精度進行控制,好比四捨五入保留兩位小數等。
public static void main(String[] args) { //四捨五入保留兩位小數 BigDecimal bigDecimal = new BigDecimal("2.555"); bigDecimal = bigDecimal.setScale(2, RoundingMode.HALF_UP); System.out.println(bigDecimal.toString()); //向上取整 bigDecimal = bigDecimal.setScale(0, RoundingMode.CEILING); System.out.println(bigDecimal); //向下取整 bigDecimal = new BigDecimal("2.1"); bigDecimal = bigDecimal.setScale(0, RoundingMode.FLOOR); System.out.println(bigDecimal.toString()); } //輸出結果 /** 2.56 3 2 */
BigDecimal是不可變的,因此每一次操做都會建立一個新的BigDecimal對象。