51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

财务说账单上少了一分钱,老板看到代码气疯了

# (一)前言 {#一-前言}

在刚学Java的时候,我们老师就和我们说float和double的精度是存在误差的,原因在于二进制中没有准确表示比如0.1,0.00001这样的数据,甚至于操作系统的位数也会影响到float和double的精度。刚好前几天遇到了这样一个问题,一个财务对接系统反馈金额账上对应不上,检查历史代码后发现竟然有人用float去修饰了金额,导致计算后精度误差。

    public static void main(String[] args) {
        float a=50.49f;
        System.out.println(a);
        System.out.println(a*10);
    }

1
2
3
4
5

比如这段代码,结果是:

50.49
504.90002

1
2

这已经是很低级的错误了。

# (二)Java中如何处理金额 {#二-java中如何处理金额}

Java中提供了一个类BigDecmal来进行精确计算,BigDecmal中提供了多种构造方法,但是如果是金额相关数据,建议一定要使用String来构造。

    public static void main(String[] args) {
        float a=50.49f;
        String a2=String.valueOf(a);
        BigDecimal bigDecimal=new BigDecimal(a);
        System.out.println(bigDecimal);  //输出50.490001678466796875
        BigDecimal bigDecimal2=new BigDecimal(a2);
        System.out.println(bigDecimal2); //输出50.49
    }

1
2
3
4
5
6
7
8

原因通过代码就可以看出来了,使用float构造方法,转换出来的数据依旧是不精确的。

BigDecimal的操作最常用的就是加减乘除,他也提供了这一系列的方法:

    public static void main(String[] args) {
        BigDecimal bigDecimal=new BigDecimal("50.49");
        System.out.println(bigDecimal);
        System.out.println(bigDecimal.add(new BigDecimal("10")));  //加
        System.out.println(bigDecimal.subtract(new BigDecimal("10")));  //减
        System.out.println(bigDecimal.multiply(new BigDecimal("10")));  //乘
        System.out.println(bigDecimal.divide(new BigDecimal("10")));  //除
    }

1
2
3
4
5
6
7
8

有关BigDecimal的更多操作可以查阅官方文档。

除了使用BigDecimal之外,还可以换个思路。比如一个金额如果需要保留两位小数,那么我们就可以在计算时按分来计算,比如100元就是10000分,这个10000分是整型。不过还是建议使用BigDecimal。

# (三)Mysql中如何存储金额 {#三-mysql中如何存储金额}

在Mysql中,可以用decimal字段记录金额:

`money` DECIMAL(18,2) not null comment '金额'

1

同时也能用varchar以字符串的方式保存

或者通过int或者bigint来存储以分为单位的金额。

具体如何选择,还是要看项目中如何使用。

# (四)总结 {#四-总结}

总结一句,凡是代码中和钱打交道的业务,务必要小心谨慎,多测试几遍。不然出事情之后很难收尾。我是鱼仔,我们下期再见!

赞(1)
未经允许不得转载:工具盒子 » 财务说账单上少了一分钱,老板看到代码气疯了