浮点类型金额字段计算精度问题

目录

项目场景

问题描述

原因分析

解决方案

总结


项目场景

银行风控系统,累积某个卡一天的累积金额=0.3时触发一个规则。如我今天发生了两笔交易,第一笔0.1完成后数据库保存了0.1,第二笔0.2发生后我们在做规则命中完成后需要将数据库中的0.1加上当前这一笔0.2的金额进行判断是否满足规则


问题描述

最近的项目中发现一个问题,在进行double数据类型的金额字段进行计算的时候发现结果不能符合预期,如double a=0.1;double b=0.2; double c=a+b; 得到的c并不是0.3而是0.30000000000000004,也就是说0.1+0.2不等于0.3
 

public static void main(String[] args) {
        double a=0.1;
        double b =0.2;
        double c = a+b;
        System.out.println(c);
    }

原因分析

1. 二进制表示:计算机使用二进制来表示浮点数,而不是十进制。在二进制系统中,一些十进制小数无法被准确地表示为有限的二进制小数。例如,0.1(十进制)在二进制中是无限循环的小数。当你将其转换为二进制表示时,会出现舍入误差,例如:0.1(十进制)=0.0001100110011001(二进制)

2. 有限精度:浮点数的表示是有限的,无法精确地表示所有的实数。例如,double类型使用64位表示,其中一部分用于表示符号、指数和小数部分。由于位数的限制,某些小数无法精确表示,因此会出现舍入误差。

注: 这个问题和是什么语言以及什么程序无关,计算机底层运算都是这样的


解决方案

具体的解决方法有两个:

1. 直接将double数值进行四舍五入后在进行运算,我在项目中使用了这种方式

2. 不要使用浮点类型,全部用int因为如果是单笔交易的金额的话int的大小足够用了,然后直接进行加减运算

public static double rounding(double value) {
    BigDecimal result = new BigDecimal(String.valueOf(value)).setScale(2, 
    BigDecimal.ROUND_HALF_UP);
    return result.doubleValue();
}

总结

项目中需要用到浮点类型的数值计算需要特别注意这一点,而且需要基于业务来考虑应该使用什么数据类型,保留几位小数等问题。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值