解决浮点类型在商业运算中的精度丢失问题

解决浮点类型在商业运算中的精度丢失问题

导言:money一直是一个敏感的话题,商业运算中money的计算显得有为重要,我们知道在java中浮点类型float,double在运算中会出现精度丢失的问题

场景:例如某用户有10块钱,买了一件商品花了8.8,理应剩下1.2元。但却无法继续购买价格为1.2元的商品,这就出现了1.2+8.8不等于10的现象,用户就会觉得特别不合理,明明是10块的东西而十块钱却买不到。这就是浮点数在商业运算中出现精度丢失所带来的严重问题。

解决浮点类型在商业运算中的精度丢失问题_第1张图片

针对以上问题笔者认为有两种解决方案:

第一种:

在设计数据库表的时候可以将price字段类型设置为int(oracle应设置为number)类型,而在实体中对应的属性单位应该表示为分(即精确到0.00)或者角(即0.0),但一般情况下money会精确到分。这里只是说明这个问题的解决思想

例如:

在商品实体类中:

public class item{

private String id;

private String name;

private int price;

....

//get,set方法...

}

如果商品的价格为12.53元(精确到分)

在数据库中price字段对应的数据为应该为1253

使用这种方法需要编程人员自己在程序中收懂转换,当然也可以封装为一个工具类。

第二种:

使用java提供的BigDecimal类。该类封装在java.math.BigDecimal中

该类的构造器有很多,但在使用浮点类型计算时一定要使用String构造器来实例BigDecimal对象,要不然还是解决不了问题的

使用方法:

//加法

 public static BigDecimal add(double v1,double v2){
        BigDecimal b1 = new BigDecimal(Double.toString(v1));//这里使用的是String构造器
        BigDecimal b2 = new BigDecimal(Double.toString(v2));//将double转换为String类型
        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);//这是b1-b2,可以理解为从b1截取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);//四舍五入,保留2位小数,除不尽的情况
    }

以上方法也可封装在一个工具类中,在编程调用的时候回比较优雅一点

如果想更清楚的了解bigDecimal可以看看原码,或者百度看看别人对bigdecimal更详细的介绍,楼主主要在这里介绍解决方案

以上就是楼主所知的如何在商业运算中解决精度丢失的解决方案,可能还有其他方法吧。

个人意见,仅供参考,不喜勿喷。

你可能感兴趣的:(解决浮点类型在商业运算中的精度丢失问题)