BigDecimal解决商业运算中丢失精度的问题

记得有一次去面试Java软件开发工程师,面试官问了我一个关于Java如何解决商业运算中的精度丢失的问题.我顿时慌了,我没有反应过来,因为我对为什么会产生这个问题以及这个问题的解决方案一点印象也没有.平时工作中的确也用到过,但是那也是前辈们封装好的,我直接拿来用,我只是知道这个工具类是用来浮点型计算,也没去看里面的具体实现,更加不知道这个工具类是为了解决Java在商业运算中精度丢失的问题.面试完成后,我回到家查阅资料才知道,在JAVA中,用浮点型计算某些数值的时候会变成科学计数.

BigDecimal在浮点型数据计算丢失精度的常见案例:

package com.mmall.test;
 
import org.junit.Test;
 
import java.math.BigDecimal;
 
/**
 * Created by Administrator on 2017/10/20.
 */
public class BigDecimalTest {
 
    //和想象不太一样,很容易丢失精度
    //很多语言都有专门的货币计算,java没有
    //java在浮点型运算过程中会丢失精度
    //很可能造成一个用户有10元钱不能购买9.9999元的商品
    @Test
    public void test1(){
        System.out.println(0.05+0.01);
        System.out.println(1.0+0.42);
        System.out.println(4.015*100);
        System.out.println(123.3/100);
        /*
        0.060000000000000005
        1.42
        401.49999999999994
        1.2329999999999999
         */
 
    }
 
    @Test
    public void test2(){
        BigDecimal b1 = new BigDecimal(0.05);
        BigDecimal b2 = new BigDecimal(0.01);
        //b1.add(b2);
        System.out.println(b1.add(b2));
        //0.06000000000000000298372437868010820238851010799407958984375
        //又长又乱
    }
 
    @Test
    public void test3(){
        BigDecimal b1 = new BigDecimal("0.05");
        BigDecimal b2 = new BigDecimal("0.01");
        System.out.println(b1.add(b2));
        //0.06
        //用string 构造器,完美解决
    }
}

 通过上面的测试可知,使用BigDecimal的string构造器,可以完美解决这个问题。

下面封装一个BigDecimalUntil工具类,方便以后使用:

package com.mmall.until;
 
import java.math.BigDecimal;
 
/**
 * Created by Administrator on 2017/10/20.
 */
public class BigDecimalUntil {
 
    //使构造器不能在外部实例化
    private BigDecimalUntil(){
 
    }
 
    public static BigDecimal add(double v1,double 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));
        return b1.divide(b2,2,BigDecimal.ROUND_HALF_UP);
        //除不尽的时候要四舍五入,并且保留几位小数
    }
}

参考文章来源:https://blog.csdn.net/sinat_32133675/article/details/78310616

猜你喜欢

转载自blog.csdn.net/qq_36090463/article/details/81084808