當您在計算Money的時候,請看好了!!!要不損失了別后悔!!!
現象1:
public static void main(String[] args) {
System.out.println(0.030*100);//輸出3.0
System.out.println(0.031*100);//輸出3.1
System.out.println(0.032*100);//輸出3.2
System.out.println(0.033*100);//輸出3.3000000000000003
System.out.println(0.034*100);//輸出3.4000000000000004
System.out.println(0.035*100);//輸出3.5000000000000004
System.out.println(0.036*100);//輸出3.5999999999999996
System.out.println(0.037*100);//輸出3.6999999999999997
System.out.println(0.038*100);//輸出3.8
System.out.println(0.039*100);//輸出3.9
}
|
現象2:
public static void main(String[] args) {
BigDecimal b1 = new BigDecimal("0.236");
BigDecimal b2 = new BigDecimal(0.236);
System.out.println(b1);//輸出0.236
System.out.println(b2);//輸出0.2359999999999999875655021241982467472553253173828125
}
|
描述:
當我們使用一些“特殊的數字”進行運算時,或者調用BigDecimal中new BigDecimal(double
val)進行構造的時候,將得到意想不到的結果。
原因:
Java中,浮點類型是依據IEEE754標準的。IEEE754定義了32位和64位雙精度兩種浮點二進制小數標準。采用二進制表示double,float等浮點數是不準確的。
同時BigDecimal的API聲明,建議使用new BigDecimal(String val)進行構造,使用new BigDecimal(double val)進行構造的時候,將得到意想不到的結果(The results of this constructor can be
somewhat unpredictable)。
解決辦法(以0.236*100 = 23.599999999999998為例):
1、 通過String結合BigDecimal來轉換。
String val = "0.236";
//使用new BigDecimal(String val)進行構造
BigDecimal a = new BigDecimal(""+val);
BigDecimal b = new BigDecimal(""+100);
//小數的位數與構造參數的位數一致
System.out.println(a.multiply(b));//輸出23.600
|
2、 通過移位結合BigDecimal來轉換
String val = "0.236";
//使用new BigDecimal(String val)進行構造
BigDecimal a = new BigDecimal(""+val);
//向右移兩位
a = a.movePointRight(2);
System.out.println(a);//輸出23.6
|
3、 使用保留小數位的方法來轉換
double result = 0.236*100;
System.out.println(result);//輸出23.599999999999998
//計算保留result小數點后四位,以此類推,1后面幾個零就是保留小數點后幾位數.如下保留兩位小數
result = (double)(Math.round(result*100)/100.0)
;
System.out.println(result);//輸出23.6
|
4、 使用DecimalFormat來確定小數點后位數
double val = 0.236*100;
//保留小數點后兩位,若保留三位為"#.000"
DecimalFormat df = new DecimalFormat("#.00");
String str = df.format(val);
System.out.println(Double.valueOf(str));//輸出23.6
|
5、-----方法很多,一個即可
心得:
處理這樣的精度問題方法很多,只要不是直接采用浮點數進行計算就行。
附加:
IEEE 754用科學記數法以底數為2的小數來表示浮點數。32位浮點數用1位表示數字的符號,用8位來表示指數,用23位來表示尾數,即小數部分。作為有符號整數的指數可以有正負之分。小數部分用二進制(底數2)小數來表示。對于64位雙精度浮點數,用1位表示數字的符號,用11位表示指數,52位表示尾數。如下兩個圖來表示:
float(32位):
double(64位):
都是分為三個部分:
(1)一個單獨的符號位s直接編碼符號s。
(2)k位的冪指數E,移碼表示。
(3)n位的小數,原碼表示。
posted on 2010-10-26 12:04
墻頭草 閱讀(3703)
評論(0) 編輯 收藏