Java中BigDecimal的使用(1.01+2.02=3.0300000000000002)

weixin_37821107發表於2018-07-26

轉載於:https://blog.csdn.net/cen_s/article/details/76472834

在日常開發中我們經常會碰到小數計算,而小數直接計算的話會出現一些小小的錯誤,如下


System.out.println(1.01 + 2.02);

你說能輸出什麼?3.03?實際上輸出的是3.0300000000000002。這是因為不論是float 還是double都是浮點數,而計算機是二進位制的,浮點數會失去一定的精確度。有沒有不失精度的辦法呢?這裡就要用到BigDecimal了。

java.math.BigDecimal。Java在java.math包中提供的API類BigDecimal,用來對超過16位有效位的數進行精確的運算。雙精度浮點型變數double可以處理16位有效數。在實際應用中,需要對更大或者更小的數進行運算和處理。float和double只能用來做科學計算或者是工程計算,在商業計算中要用java.math.BigDecimal。BigDecimal所建立的是物件,我們不能使用傳統的+、-、*、/等算術運算子直接對其物件進行數學運算,而必須呼叫其相對應的方法。方法中的引數也必須是BigDecimal的物件。構造器是類的特殊方法,專門用來建立物件,特別是帶有引數的物件。

建立BigDecimal物件主要有兩種。

  1. BigDecimal b1 = new BigDecimal("1.34");//1.34
  2. BigDecimal b2 = BigDecimal.valueOf(1.34);//1.34

其中b1也可以寫成new BigDecimal(Double.toString(1.34)),可以直接new BigDecimal(1.34)嗎,也是可以的,只是會出現上述的精度問題。

  1. BigDecimal one1 = new BigDecimal(1.34);//1.3400000000000000799360577730112709105014801025390625
  2. BigDecimal two1 = new BigDecimal("1.34");//1.34

除了這兩種外,特殊的像0、1、10可以這樣寫。

  1. BigDecimal zero = BigDecimal.ZERO;
  2. BigDecimal one = BigDecimal.ONE;
  3. BigDecimal ten = BigDecimal.TEN;


比較一下BigDecimal.ZERO、new BigDecimal(“0”)、BigDecimal.valueOf(0)這三者,equals都是true,==的話new BigDecimal(“0”)就不用看了都new了,而BigDecimal.ZERO == BigDecimal.ZERO為true。檢視一下原始碼可得。


  1. public static BigDecimal valueOf(long val) {
  2. if (val >= 0 && val < zeroThroughTen.length)
  3. return zeroThroughTen[(int)val];
  4. else if (val != INFLATED)
  5. return new BigDecimal(null, val, 0, 0);
  6. return new BigDecimal(INFLATED_BIGINT, val, 0, 0);
  7. }

  1. // Cache of common small BigDecimal values.
  2. private static final BigDecimal zeroThroughTen[] = {
  3. new BigDecimal(BigInteger.ZERO, 0, 0, 1),
  4. new BigDecimal(BigInteger.ONE, 1, 0, 1),
  5. new BigDecimal(BigInteger.valueOf(2), 2, 0, 1),
  6. new BigDecimal(BigInteger.valueOf(3), 3, 0, 1),
  7. new BigDecimal(BigInteger.valueOf(4), 4, 0, 1),
  8. new BigDecimal(BigInteger.valueOf(5), 5, 0, 1),
  9. new BigDecimal(BigInteger.valueOf(6), 6, 0, 1),
  10. new BigDecimal(BigInteger.valueOf(7), 7, 0, 1),
  11. new BigDecimal(BigInteger.valueOf(8), 8, 0, 1),
  12. new BigDecimal(BigInteger.valueOf(9), 9, 0, 1),
  13. new BigDecimal(BigInteger.TEN, 10, 0, 2),
  14. };

發現10以內的物件都是同一個,所以為true。


BigDecimal的加減乘除運算。

  1. public BigDecimal add(BigDecimal value);//加法
  2. public BigDecimal subtract(BigDecimal value);//減法
  3. public BigDecimal multiply(BigDecimal value);//乘法
  4. public BigDecimal divide(BigDecimal value);//除法
也可以照下面加法例子寫成一個util,另外三個都差不多就不展開了。

  1. public static double add(double value1,double value2){
  2. BigDecimal b1 = new BigDecimal(Double.toString(value1));
  3. BigDecimal b2 = new BigDecimal(Double.toString(value2));
  4. return b1.add(b2).doubleValue();
  5. }
BigDecimal的運算都沒有對原值進行操作,而是返回一個新的BigDecimal物件,這點可能有些小夥伴會搞錯要注意一下。
  1. BigDecimal b1 =new BigDecimal("1.34");
  2. System.out.println("b1: " + b1);
  3. BigDecimal b2 =new BigDecimal("2.34");
  4. b1.add(b2);
  5. System.out.println("b1: " + b1);//b1並沒有變
BigDecimal的比較用的是BigDecimal的compareTo方法,將此 BigDecimal 與指定的 BigDecimal 比較。

根據此方法,值相等但具有不同標度的兩個BigDecimal物件(如,2.0 和 2.00)被認為是相等的。

當此 BigDecimal 在數字上小於、等於或大於被比較物件時,返回 -1、0 或 1。

  1. BigDecimal one = BigDecimal.valueOf(1);
  2. BigDecimal two = BigDecimal.valueOf(2);
  3. BigDecimal three = one.add(two);
  4. int i1 = one.compareTo(two);//-1
  5. int i2 = two.compareTo(two);//0
  6. int i3 = three.compareTo(two);//1







            </div>

相關文章