java中關於精度丟失的情況:
System.out.println(0.05 + 0.01); System.out.println(1.0 - 0.42); System.out.println(4.015 * 100); System.out.println(123.3 / 100);輸出的結果爲:
0.060000000000000005
0.5800000000000001
401.49999999999994
1.2329999999999999
----------------------------------------------------------------------------------------------------
而使用BigDecimal的String構造器
BigDecimal b1 = new BigDecimal("0.05"); BigDecimal b2 = new BigDecimal("0.01"); System.out.println(b1.add(b2));使用String構造器其結果爲:0.06;
在BigDecimal源碼中有說明:如果使用BigDecimal中double構造器,其運算結果會無限接近正確結果:
如:
BigDecimal b1 = new BigDecimal(0.05); BigDecimal b2 = new BigDecimal(0.01); System.out.println(b1.add(b2));
使用double構造器其結果爲:0.06000000000000000298372437868010820238851010799407958984375,比結果大,既無限接近正確結果;
源碼中的說明大概爲:如果要使用double這個構造器,就要把參數使用Double的toString的方法(方法裏面放double)轉換爲String,
然後使用BigDecimal(String)去構造,即:我們要用的話:要把double轉爲String,然後還要用BigDecimal的String構造器.
在價格運算應用中一定要用BigDecimal的String構造器;
封裝成一個BigDecimalUtil:
public class BigDecimalUtil { private BigDecimalUtil() {} // + public static BigDecimal add(double v1, double v2) { //轉換爲String,然後就會調用String構造器 BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.add(b2); } // - public static BigDecimal sub(double v1, double v2) { //轉換爲String,然後就會調用String構造器 BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.subtract(b2); } // * public static BigDecimal mul(double v1, double v2) { //轉換爲String,然後就會調用String構造器 BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.multiply(b2); } // / public static BigDecimal div(double v1, double v2) { //轉換爲String,然後就會調用String構造器 BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); //要考慮除不盡的情況(更多需求需瞭解divide源碼 return b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP);//四捨五入,保留兩位小數 } }