JAVA-精確計算時的陷阱

java.math包中有個BigDecimal類,通過這個類可以進行精確計算. 我們知道BigDecimal有個setScale(int 精度,int 舍入模式)方法,隨之而來問題出現了,當運行如下代碼時:

卻驚奇地打印出結果:

0.82

 

Oh My God,對0.825進行小數點後保留2位有效數字,四捨五入後結果應該是:0.83。爲什麼打印結果是0.82

 

沒錯BigDecimaldouble val)這個構造器欺騙了我們,它使用了0.825的近似值(0.8249999999999……)來構造BigDecimal

爲什麼會這樣?

 

原來JAVA存儲浮點數(floatdouble)時,使用的是IEEE754標準,每個浮點數使用的是 符號位、階碼、尾數來表示:

````````符號位  階碼   尾數    長度
float     1      8      23       32
double    1      11     52       64

通過這種方法保存在計算機裏面的浮點數,實際上是它的近似值。舉例說明問題:

定義一個double 38414.4,將它轉換爲16進制。我們先計算整數部分38414等於960E。小數處理:0.4=0*0.5+0.25*1+0.0625*0+……,實際上我們永遠計算不完。

結論:當我們定義一個浮點數時,請告訴自己,我們定義只不過是這個浮點數的近似值,即0.825!=0.825

 

爲了避免這個問題,我們應該使用如下方法:

使用BigDecimalString val)構造器,這段代碼運行的結果是:0.83

 

由此可見BigDecimaldouble val)這個構造器完全就是一個陷阱。

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