BigDecimal中要注意的一些事
一、關於public BigDecimal(double val)
BigDecimal中三個主要的建構函式
1 |
public BigDecimal(double val) |
將double表示形式轉換為BigDecimal |
不推薦 |
2 |
public BigDecimal(int val) |
將int表示形式轉換為BigDecimal |
推薦 |
3 |
public BigDecimal(String val) |
將字串表示形式轉換為BigDecimal |
推薦 |
不推薦用 BigDecimal(double val)的原因是因為存在精度問題,如下圖:
如果要探究造成這個問題的原因其實和BigDecimal沒有關係;
原因:這其實和計算機使用二進位制編碼有關,在你使用BigDecimal(Double val)傳入0.1時,這個0.1先被轉換為Double,此時就已經出現了精度問題了,計算機只能用有限位數儲存小數【二進位制能用有限的位數表示的小數有:0.5、0.25、0.125 等】,所以儲存的小數大多為一個近似值,十進位制的 0.1 轉為二進位制,得到一個無限迴圈小數,所以傳入到BigDecimal(Double val)中的數精度已經出現問題了,而BigDecimal又是為精確結果而設計的,所以bDouble就不是我們想要的0.1。
如何解決:
一、使用BigDecimal b1 = new BigDecimal("0.1");將資料轉成String再使用BigDecimal(String val);
二、使用BigDecimal b1 = BigDecimal.valueOf(0.1);使用BigDecimal的valueOf()方法;
開啟BigDecimal的valueOf()的原始碼
可以看到它也是直接轉成String型別再呼叫BigDecimal(String val);方法
二、關於Non-terminating decimal expansion; no exact representable decimal result
Non-terminating decimal expansion; no exact representable decimal result. 翻譯為:非終止十進位制擴充套件; 沒有確切的可表示的小數結果;
翻譯為人話就是說:BigDecimal是為高精度計算而設計的,而你的值是沒有精確結果的;
舉例:
1.0/3.0是除不盡的,所以丟擲異常
解決方案:使用BigDecimal.divide(BigDecimal divisor, int scale, RoundingMode roundingMode) ;
其中 scale 為保留的小數位;RoundingMode roundingMode 為取捨模式(如:RoundingMode.HALF_UP 四捨五入);
RoundingMode具有哪些模式請參照我的另一篇部落格:https://www.cnblogs.com/minxl/p/10247770.html