天天看點

[轉]Java中BigDecimal的使用

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

你說能輸出什麼?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對象主要有兩種。

BigDecimal b1 = new BigDecimal("1.34");//1.34

BigDecimal b2 = BigDecimal.valueOf(1.34);//1.34

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

BigDecimal one1 = new BigDecimal(1.34);//1.3400000000000000799360577730112709105014801025390625

BigDecimal two1 = new BigDecimal("1.34");//1.34

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

BigDecimal zero = BigDecimal.ZERO;

BigDecimal one = BigDecimal.ONE;

BigDecimal ten = BigDecimal.TEN;

比較一下BigDecimal.ZERO、new BigDecimal("0")、BigDecimal.valueOf(0)這三者,equals都是true,==的話new BigDecimal("0")就不用看了都new了,而BigDecimal.ZERO

== BigDecimal.ZERO為true。檢視一下源代碼可得。

public static BigDecimal valueOf(long val) {

if (val >= 0 && val < zeroThroughTen.length)

return zeroThroughTen[(int)val];

else if (val != INFLATED)

return new BigDecimal(null, val, 0, 0);

return new BigDecimal(INFLATED_BIGINT, val, 0, 0);

}

// Cache of common small BigDecimal values.

private static final BigDecimal zeroThroughTen[] = {

new BigDecimal(BigInteger.ZERO, 0, 0, 1),

new BigDecimal(BigInteger.ONE, 1, 0, 1),

new BigDecimal(BigInteger.valueOf(2), 2, 0, 1),

new BigDecimal(BigInteger.valueOf(3), 3, 0, 1),

new BigDecimal(BigInteger.valueOf(4), 4, 0, 1),

new BigDecimal(BigInteger.valueOf(5), 5, 0, 1),

new BigDecimal(BigInteger.valueOf(6), 6, 0, 1),

new BigDecimal(BigInteger.valueOf(7), 7, 0, 1),

new BigDecimal(BigInteger.valueOf(8), 8, 0, 1),

new BigDecimal(BigInteger.valueOf(9), 9, 0, 1),

new BigDecimal(BigInteger.TEN, 10, 0, 2),

};

發現10以内的對象都是同一個,是以為true。

BigDecimal的加減乘除運算。

public BigDecimal add(BigDecimal value);//加法

public BigDecimal subtract(BigDecimal value);//減法

public BigDecimal multiply(BigDecimal value);//乘法

public BigDecimal divide(BigDecimal value);//除法

也可以照下面加法例子寫成一個util,另外三個都差不多就不展開了。

public static double add(double value1,double value2){

BigDecimal b1 = new BigDecimal(Double.toString(value1));

BigDecimal b2 = new BigDecimal(Double.toString(value2));

return b1.add(b2).doubleValue();

BigDecimal的運算都沒有對原值進行操作,而是傳回一個新的BigDecimal對象,這點可能有些小夥伴會搞錯要注意一下。

BigDecimal b1 =new BigDecimal("1.34");

System.out.println("b1: " + b1);

BigDecimal b2 =new BigDecimal("2.34");

b1.add(b2);

System.out.println("b1: " + b1);//b1并沒有變

BigDecimal的比較用的是BigDecimal的compareTo方法,将此 BigDecimal 與指定的 BigDecimal 比較。

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

當此 BigDecimal 在數字上小于、等于或大于被比較對象時,傳回 -1、0 或 1。

BigDecimal one = BigDecimal.valueOf(1);

BigDecimal two = BigDecimal.valueOf(2);

BigDecimal three = one.add(two);

int i1 = one.compareTo(two);//-1

int i2 = two.compareTo(two);//0

int i3 = three.compareTo(two);//1