# (一)前言 {#一-前言}
在刚学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来存储以分为单位的金额。
具体如何选择,还是要看项目中如何使用。
# (四)总结 {#四-总结}
总结一句,凡是代码中和钱打交道的业务,务必要小心谨慎,多测试几遍。不然出事情之后很难收尾。我是鱼仔,我们下期再见!