API
构造器
构造器 | 描述 |
---|
BigDecimal(int) | 创建一个具有参数所指定整数值的对象。 |
BigDecimal(double) | 创建一个具有参数所指定双精度值的对象。 |
BigDecimal(long) | 创建一个具有参数所指定长整数值的对象。 |
BigDecimal(String) | 创建一个具有参数所指定以字符串表示的数值的对象。 |
方法
方法 | 描述 |
---|
add(BigDecimal) | BigDecimal对象中的值相加,然后返回这个对象。 |
subtract(BigDecimal) | BigDecimal对象中的值相减,然后返回这个对象。 |
multiply(BigDecimal) | BigDecimal对象中的值相乘,然后返回这个对象。 |
divide(BigDecimal) | BigDecimal对象中的值相除,然后返回这个对象。 |
toString() | 将BigDecimal对象的数值转换成字符串。 |
doubleValue() | 将BigDecimal对象中的值以双精度数返回。 |
floatValue() | 将BigDecimal对象中的值以单精度数返回。 |
longValue() | 将BigDecimal对象中的值以长整数返回。 |
intValue() | 将BigDecimal对象中的值以整数返回。 |
精度丢失
我们在使用BigDecimal时,使用它的BigDecimal(String)构造器创建对象才有意义。其他的如BigDecimal b = new BigDecimal(1)这种,还是会发生精度丢失的问题。如下代码:
BigDecimal a = new BigDecimal(1.01);
BigDecimal b = new BigDecimal(1.02);
BigDecimal c = new BigDecimal("1.01");
BigDecimal d = new BigDecimal("1.02");
System.out.println(a.add(b));
System.out.println(c.add(d));
输出:
2.0300000000000000266453525910037569701671600341796875
2.03
可见论丢失精度BigDecimal
显的更为过分。但是使用Bigdecimal
的BigDecimal(String)
构造器的变量在进行运算的时候却没有出现这种问题。 究其原因计算机组成原理里面都有,它们的编码决定了这样的结果。long
可以准确存储19位数字,而double
只能准备存储16位数字。double
由于有exp位,可以存16位以上的数字,但是需要以低位的不精确作为代价。如果需要高于19位数字的精确存储,则必须用BigInteger
来保存,当然会牺牲一些性能。所以我们一般使用BigDecimal
来解决商业运算上丢失精度的问题的时候,声明BigDecimal
对象的时候一定要使用它构造参数为String
的类型的构造器。
举个栗子🌰
public class BigDecimalUtil {
private BigDecimalUtil() {
}
public static BigDecimal add(double v1, double v2) {// v1 + v2
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) {
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) {
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) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
// 2 = 保留小数点后两位 ROUND_HALF_UP = 四舍五入
return b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP);// 应对除不尽的情况
}
}