double、float数值运算出现精度问题的解决方式

  最近在一直在写有关自定义View的demo,有时候绘制的View的高和我实际的结果有偏差,之前就听同事说过用java.math的BigDecimal类进行处理会更准确,今天正好有空就顺便整理下。首先写了一个DecimalUtil做测试,代码如下:

/**
 * 加运算
 */
public static double addOne(double a, double b) {
    return a + b;
}

public static double addTwo(double a, double b) {
    BigDecimal bd1 = new BigDecimal(Double.toString(a));
    BigDecimal bd2 = new BigDecimal(Double.toString(b));
    return bd1.add(bd2).doubleValue();
}

/**
 * 减运算
 */
public static double subOne(double a, double b) {
    return a - b;
}

public static double subTwo(double a, double b) {
    BigDecimal bd1 = new BigDecimal(Double.toString(a));
    BigDecimal bd2 = new BigDecimal(Double.toString(b));
    return bd1.subtract(bd2).doubleValue();
}

/**
 * 乘运算
 */
public static double mulOne(double a, double b) {
    return a * b;
}

public static double mulTwo(double a, double b) {
    BigDecimal bd1 = new BigDecimal(Double.toString(a));
    BigDecimal bd2 = new BigDecimal(Double.toString(b));
    return bd1.multiply(bd2).doubleValue();
}

/**
 * 除运算
 */
public static double divOne(double a, double b) {
    return a / b;
}

public static double divTwo(double a, double b) {
    BigDecimal aBD = new BigDecimal(Double.toString(a));
    BigDecimal bBd = new BigDecimal(Double.toString(b));
    return aBD.divide(bBd, 20, BigDecimal.ROUND_HALF_UP).doubleValue();
}
System.out.print("加"+DecimalUtil.addOne(0.05,0.025)+"--"+DecimalUtil.addTwo(0.05,0.025));
System.out.print("减"+DecimalUtil.subOne(0.05,0.025)+"--"+DecimalUtil.subTwo(0.05,0.025));
System.out.print("乘"+DecimalUtil.mulOne(0.05,0.025)+"--"+DecimalUtil.mulTwo(0.05,0.025));
System.out.print("除"+DecimalUtil.divOne(0.05,0.025)+"--"+DecimalUtil.divTwo(0.05,0.025));

运行上面的代码,在控制台打印结果如下:

double、float数值运算出现精度问题的解决方式_第1张图片

这里我们可以看到输出结果对比,浮点型数据直接运算和我们想要的结果还是有一定的误差,这里主要说明一下divide(BigDecimal divisor,int scale,int roundingMode)这个方法,scale表示保留到小数点后几位,roundingMode表示保留模式,一个提供了7种,这里就不详细说明了。还有divide(BigDecimal divisor)这个方法,这个适用于整除的两个浮点型数,非整除就不能使用,否则会报java.lang.ArithmeticException的异常。

最后说一下BigDecimal的格式化问题,由于NumberFormat的format()方法可以使用BigDecimal对象作为参数,可以使用BigDecimal对超出16位有效数字的货币值、百分比值、以及一般数值进行格式化控制。下面贴出测试的代码:

public static void format(){
    NumberFormat currency = NumberFormat.getCurrencyInstance();  //建立货币格式化引用
    NumberFormat percent = NumberFormat.getPercentInstance();    //建立百分比格式化引用
    percent.setMaximumFractionDigits(3);                         //百分比小数点最多3位

    BigDecimal loanAmount = new BigDecimal(Double.toString(100000.009));  //贷款金额
    BigDecimal interestRate = new BigDecimal(Double.toString(0.06));      //利率
    BigDecimal interest = loanAmount.multiply(interestRate);              //相乘

    System.out.println("贷款金额:" + currency.format(loanAmount));
    System.out.println("利率:" + percent.format(interestRate));
    System.out.println("利息:" + currency.format(interest));
}

输出结果如下,


这里只是简单的分享了下解决方式,有兴趣的同学还可以深入了解下!

你可能感兴趣的:([Java,基础知识])