Java中BigDecimal對象與double之間轉換涉及的精度問題及“no exact representable decimal result.”解決方案

當我們在開發的時候,有時候根據需求來講,會要求小數點後精確到幾位數,例如涉及到費用的問題,通常會讓我們精確到小數點後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)

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章