在java.math包中有個BigDecimal類,通過這個類可以進行精確計算. 我們知道BigDecimal有個setScale(int 精度,int 舍入模式)方法,隨之而來問題出現了,當運行如下代碼時:
卻驚奇地打印出結果:
0.82
Oh My God,對0.825進行小數點後保留2位有效數字,四捨五入後結果應該是:0.83。爲什麼打印結果是0.82?
沒錯BigDecimal(double val)這個構造器欺騙了我們,它使用了0.825的近似值(0.8249999999999……)來構造BigDecimal。
爲什麼會這樣?
原來JAVA存儲浮點數(float、double)時,使用的是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。
爲了避免這個問題,我們應該使用如下方法:
使用BigDecimal(String val)構造器,這段代碼運行的結果是:0.83
由此可見BigDecimal(double val)這個構造器完全就是一個陷阱。