BigDecimal使用注意事项

BigDecimal的使用

1. 使用BigDecimal表示和计算浮点数,需要使用字符串的构造方法来初始化BigDecimal
new BigDecimal("0.1").add(new BigDecimal("0.1"))// +
new BigDecimal("0.1").subtract(new BigDecimal("0.1"))// -
new BigDecimal("0.1").multiply(new BigDecimal("0.1"))// *
new BigDecimal("0.1").divide(new BigDecimal("0.1"))// /
2. 浮点数的格式化通过BigDecimal的setScale指定舍入的位数和方式
BigDecimal num1 = new BigDecimal("3.35").setScale(1, BigDecimal.ROUND_DOWN);//3.3
BigDecimal num2 = new BigDecimal("3.35").setScale(1, BigDecimal.ROUND_HALF_UP);//3.4

BigDecimal的比较

1. BigDecimal中的equals方法默认比较的是BigDecimal的value和scale[精度]如:
new BigDecimal("1.0").equals(new BigDecimal("1"))//false
因此:
比较BigDecimal的value使用compareTo方法;

2. BigDecimal中的hashCode方法默认考虑BigDecimal的value和scale[精度]如:
Set hashSet1 = new HashSet<>();
hashSet1.add(new BigDecimal("1.0")); hashSet1.contains(new BigDecimal("1"));//false 因此: 解决1:使用TreeSet替换HashSet(默认使用compareTo比较,且没有用hashCode方法)。 解决2:把BigDecimal存入HashSet或HashMap前,先使用stripTrailingZeros方法去掉尾部的零,比较的时候也去掉尾部的0,确保value相同的BigDecimal,scale也是一致的。 Set hashSet2 = new HashSet<>();
hashSet2.add(new BigDecimal("1.0").stripTrailingZeros()); hashSet2.contains(new BigDecimal("1.000").stripTrailingZeros());//true

数值溢出问题

数值溢出没有异常,解决:
1. 考虑使用Math类的addExact、subtractExact 等 xxExact 方法进行数值运算,数值溢出时会主动抛出异常(ArithmeticException->RuntimeException)
2. 使用大数类BigInteger,如把计算结果转换一个Long变量,使用BigInteger的longValueExact方法,转换溢出,抛出ArithmeticException:
new BigInteger(String.valueOf(Long.MAX_VALUE)).add(BigInteger.ONE).longValueExact();

BigDecimal工具类:高精度计算小数

public class DoubleUtils{
    private static final int DEF_DIV_SCALE = 2;

    /**
     * @Description 两个Double数相加
     *
     * @param d1
     * @param d2
     * @return Double
     */
    public static Double add(Double d1,Double d2){
        BigDecimal b1 = new BigDecimal(d1.toString());
        BigDecimal b2 = new BigDecimal(d2.toString());
        return b1.add(b2).doubleValue();
    }

    /**
     * @Description 两个Double数相减
     *
     * @param d1
     * @param d2
     * @return Double
     */
    public static Double sub(Double d1,Double d2){
        BigDecimal b1 = new BigDecimal(d1.toString());
        BigDecimal b2 = new BigDecimal(d2.toString());
        return b1.subtract(b2).doubleValue();
    }

    /**
     * @Description 两个Double数相乘
     *
     * @param d1
     * @param d2
     * @return Double
     */
    public static Double mul(Double d1,Double d2){
        BigDecimal b1 = new BigDecimal(d1.toString());
        BigDecimal b2 = new BigDecimal(d2.toString());
        return b1.multiply(b2).doubleValue();
    }

    /**
     * @Description 两个Double数相除
     *
     * @param d1
     * @param d2
     * @return Double
     */
    public static Double div(Double d1,Double d2){
        BigDecimal b1 = new BigDecimal(d1.toString());
        BigDecimal b2 = new BigDecimal(d2.toString());
        return b1.divide(b2,DEF_DIV_SCALE,BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * @Description 两个Double数相除,并保留scale位小数
     *
     * @param d1
     * @param d2
     * @param scale
     * @return Double
     */
    public static Double div(Double d1,Double d2,int scale){
        if(scale<0){
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(d1.toString());
        BigDecimal b2 = new BigDecimal(d2.toString());
        return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * @Description String类型小数与Double类型的转换
     */
    public static void strToDouble(){
        String str="1234.5678";
        double num;
        DecimalFormat myformat = new DecimalFormat("#0.00");
        num = Double.parseDouble(str);//直接转换为double类型
        num = Double.parseDouble(myformat.format(num));//保留2为小数
        System.out.println(num);
    }
}

 

posted @ 2021-12-10 17:27  白玉神驹  阅读(396)  评论(0)    收藏  举报