先看一下这个测试案例:

出现这种情况的根本原因是: 计算机的二进制,浮点数没有办法是用二进制进行精确表示;CPU表示浮点数由两个部分组成:指数和尾数,这样的表示方法一般都会失去一定的精确度,有些浮点数运算就会产生一定的误差;
所以,大多数的商业计算中,一般采用java.math.BigDecimal类来进行精确计算,有必要掌握这个类的常用方法及注意事项。
构造方法
1.public BigDecimal(double val) 将double表示形式转换为BigDecimal 不建议使用,原因看上图箭头标识
2.public BigDecimal valueOf(double val) 将double表示形式转换成BigDecimal ------推荐使用
3.public BigDecimal(String val) 将String表示形式转换成BigDecimal------推荐使用
类成员方法(加减乘除)
public BigDecimal add(BigDecimal value); //加法
public BigDecimal subtract(BigDecimal value); //减法
public BigDecimal multiply(BigDecimal value); //乘法
public BigDecimal divide(BigDecimal value); //除法
public BigDecimal divide(BigDecimal divisor,int scale, int roundingMode)://商,精度,舍取模式
关于BigDecimal的8种舍入模式 ,可以参考这篇文章,写的很详细,常用的四舍五入(ROUND_HALF_UP)
注意事项
1、应用场景:商业计算必须使用BigDecimal,比如货币计算;
2、构造函数绝对不能用第一种double类型,尽量使用参数类型为String的构造函数;
3、BigDecimal都是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象,所以在做加减乘除运算时千万要保存操作后的值。
BigDecimalUtil 示例
public class BigDecimalUtil {
// 除法运算默认精度
private static final int DEF_DIV_SCALE = 10;
/**
* 精确加法
*/
public static double add(double value1, double value2) {
BigDecimal b1 = BigDecimal.valueOf(value1);
BigDecimal b2 = BigDecimal.valueOf(value2);
return b1.add(b2).doubleValue();
}
/**
* 精确减法
*/
public static double sub(double value1, double value2) {
BigDecimal b1 = BigDecimal.valueOf(value1);
BigDecimal b2 = BigDecimal.valueOf(value2);
return b1.subtract(b2).doubleValue();
}
/**
* 精确乘法
*/
public static double mul(double value1, double value2) {
BigDecimal b1 = BigDecimal.valueOf(value1);
BigDecimal b2 = BigDecimal.valueOf(value2);
return b1.multiply(b2).doubleValue();
}
/**
* 精确除法 使用默认精度
*/
public static double div(double value1, double value2) throws IllegalAccessException {
return div(value1, value2, DEF_DIV_SCALE);
}
/**
* 精确除法
* @param scale 精度
*/
public static double div(double value1, double value2, int scale) throws IllegalAccessException {
if(scale < 0) {
throw new IllegalAccessException("精确度不能小于0");
}
BigDecimal b1 = BigDecimal.valueOf(value1);
BigDecimal b2 = BigDecimal.valueOf(value2);
return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 四舍五入
* @param scale 小数点后保留几位
*/
public static double round(double v, int scale) throws IllegalAccessException {
return div(v, 1, scale);
}
/**
* 比较大小
*/
public static boolean equalTo(BigDecimal b1, BigDecimal b2) {
if(b1 == null || b2 == null) {
return false;
}
return 0 == b1.compareTo(b2);
}
}
参考资料:Java中的BigDecimal类使用 Java BigDecimal详解
6万+

被折叠的 条评论
为什么被折叠?



