當我們在開發的時候,有時候根據需求來講,會要求小數點後精確到幾位數,例如涉及到費用的問題,通常會讓我們精確到小數點後4位,就類似於“0.3333”的格式,當我們在想要進行精確到小數點後幾位時,這時候就會想到BigDeimal對象來進行轉化,不過在進行轉化的過程中,筆者遇見了幾個不小的“坑”。
1.BigDecimal的構造方法
我們來看看JDK1.8中對BigDecimal對象是如何解釋他的構造方法的吧。
我們今天主要說一下BigDecimal對象中構造方法傳入double與String的區別。我們來通過一些代碼來看一下兩者的實際效果
1)BigDecimal(double val)
當我們想要保留小數點後四位小數,構造方法爲double時,會出現什麼情況呢?
當我們直接定義一個double數據a,通過BigDecimal對象進行轉換時,發現並沒有精度的損失,
但是,當我們設置另外一個double數據b時,兩個double數據做除運算,我們來看一看發生了什麼
我們會發現,當我們直接打印出 a / b 時,此時未做轉換,c 爲 0.85;但是當我們把 a / b 的結果放入構造方法中時(即把0.85放入構造方法中),會發現,最後通過BigDecimal對象轉化出的double數據爲0.8499;
所以我們可以得出一個結論,當BigDecimal構造方法對象爲double時,會出現精度的損失。
這時候可能會有人說,你構造方法中傳入的是 “a / b”,那是否是a/b運算出現的精度損失,而並非是構造方法中直接傳入的double出現的精度損失?
首先,第一點,double型數據做運算得出的結果同樣也是double型數據,第二點,我們來看看系統的運算結果:
所以,綜上我們可以得出一個結論,即:當BigDecimal構造方法對象爲double時,會出現精度的損失。
彩蛋:我們沒限制BigDecimal的位數的時候,它的值是多少呢?
這時候我不得不懷疑,double本身可能就是個有問題的數據呀【滑稽】
2)BigDecimal(String val)
我們同樣做一個實驗,把步驟1中傳入的double數據改爲String類型時,會發現這樣一個有趣的現象。
很神奇,當傳入的是String時,並未出現精度的損失,amazing
所以!我大膽瞎猜!double是基本數據類型!有位數限制!可能內部早就做了四捨五入的處理!String沒有位數限制!所以沒有精度損失![這句話我瞎說的]
還有一個地方需要大家注意,當在做double數據除運算的時候,中間轉爲String可以,但是還有一個方法,就是把doule都轉爲BigDecimal對象,然後再做除運算;
注意圈出的部分,如果不設置這一步,並且是有無限循環時,就會報錯:
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1690)
at TestProject.main(TestProject.java:18)