一、BigDecimal概述
Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理。一般情况下,对于那些不需要准确计算精度的数字,我们可以直接使用Float和Double处理,但是Double.valueOf(String) 和Float.valueOf(String)会丢失精度。所以开发中,如果我们需要精确计算的结果,则必须使用BigDecimal类来操作。
BigDecimal所创建的是对象,故我们不能使用传统的+、-、*、/ 等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。
二、BigDecimal常用构造函数
-
BigDecimal(int)
创建一个具有参数所指定整数值的对象
-
BigDecimal(double)
创建一个具有参数所指定双精度值的对象
-
BigDecimal(long)
创建一个具有参数所指定长整数值的对象
-
BigDecimal(String)
创建一个具有参数所指定以字符串表示的数值的对象
@Test
public void test03(){
System.out.println(new BigDecimal(1));
System.out.println(new BigDecimal(1.0d));
System.out.println(new BigDecimal(1l));
System.out.println(new BigDecimal("1"));
System.out.println(new BigDecimal(1.01));
System.out.println(new BigDecimal(1.01d));
System.out.println(new BigDecimal(1.01f));
System.out.println(new BigDecimal("1.01"));
}
运行结果 :
1
1
1
1
1.0100000000000000088817841970012523233890533447265625
1.0100000000000000088817841970012523233890533447265625
1.0099999904632568359375
1.01
三、BigDecimal常用方法
3.1 常用方法
-
add(BigDecimal)
BigDecimal对象中的值相加,返回BigDecimal对象
-
subtract(BigDecimal)
BigDecimal对象中的值相减,返回BigDecimal对象
-
multiply(BigDecimal)
BigDecimal对象中的值相乘,返回BigDecimal对象
-
divide(BigDecimal)
BigDecimal对象中的值相除,返回BigDecimal对象
-
toString()
将BigDecimal对象中的值转换成字符串
-
doubleValue()
将BigDecimal对象中的值转换成双精度数
-
floatValue()
将BigDecimal对象中的值转换成单精度数
-
longValue()
将BigDecimal对象中的值转换成长整数
-
intValue()
将BigDecimal对象中的值转换成整数
3.2、BigDecimal大小比较
BigDecimal(long) 和BigDecimal(int),因为是整数,所以精度就是0,而对于BigDecimal(double) ,当我们使用new BigDecimal(1.01)创建一个BigDecimal 的时候,其实创建出来的值并不是正好等于1.01的,而BigDecimal(String),那么new BigDecimal("1.01")创建出来的数的精度已经是可以确定的,就是1.01,精度也就是2。
BigDecimal中equals方法比较value和scale(数值和精度),精度不一样,也返回false;
/**
* Compares this {@code BigDecimal} with the specified
* {@code Object} for equality. Unlike {@link
* #compareTo(BigDecimal) compareTo}, this method considers two
* {@code BigDecimal} objects equal only if they are equal in
* value and scale (thus 2.0 is not equal to 2.00 when compared by
* this method).
*
* @param x {@code Object} to which this {@code BigDecimal} is
* to be compared.
* @return {@code true} if and only if the specified {@code Object} is a
* {@code BigDecimal} whose value and scale are equal to this
* {@code BigDecimal}'s.
* @see #compareTo(java.math.BigDecimal)
* @see #hashCode
*/
@Override
public boolean equals(Object x) {
if (!(x instanceof BigDecimal))
return false;
BigDecimal xDec = (BigDecimal) x;
if (x == this)
return true;
if (scale != xDec.scale)
return false;
long s = this.intCompact;
long xs = xDec.intCompact;
if (s != INFLATED) {
if (xs == INFLATED)
xs = compactValFor(xDec.intVal);
return xs == s;
} else if (xs != INFLATED)
return xs == compactValFor(this.intVal);
return this.inflated().equals(xDec.inflated());
}
而compareTo方法比较数值相同但是精度不同的两个数(例如2.0和2.00)被认为是相等的两个数,返回0。另外对于a.compareTo(b)方法
a=b,返回0;
a>b,返回1;
故建议对于BigDecimal,使用compareTo方法对BigDecimal比较大小。
/**
* Compares this {@code BigDecimal} with the specified
* {@code BigDecimal}. Two {@code BigDecimal} objects that are
* equal in value but have a different scale (like 2.0 and 2.00)
* are considered equal by this method. This method is provided
* in preference to individual methods for each of the six boolean
* comparison operators ({@literal <}, ==,
* {@literal >}, {@literal >=}, !=, {@literal <=}). The
* suggested idiom for performing these comparisons is:
* {@code (x.compareTo(y)} <<i>op</i>> {@code 0)}, where
* <<i>op</i>> is one of the six comparison operators.
*
* @param val {@code BigDecimal} to which this {@code BigDecimal} is
* to be compared.
* @return -1, 0, or 1 as this {@code BigDecimal} is numerically
* less than, equal to, or greater than {@code val}.
*/
public int compareTo(BigDecimal val) {
// Quick path for equal scale and non-inflated case.
if (scale == val.scale) {
long xs = intCompact;
long ys = val.intCompact;
if (xs != INFLATED && ys != INFLATED)
return xs != ys ? ((xs > ys) ? 1 : -1) : 0;
}
int xsign = this.signum();
int ysign = val.signum();
if (xsign != ysign)
return (xsign > ysign) ? 1 : -1;
if (xsign == 0)
return 0;
int cmp = compareMagnitude(val);
return (xsign > 0) ? cmp : -cmp;
}