一分钱的Bug(求助帖)

背景,某个用户反馈线上后台提现金额到账少了一分钱,其输入的提现金额是19320.38(元),但实际银行到账金额1932037(分),也就是少了一分钱。然后立马翻看代码,以及运行日志。

伪代码如下:

less 复制代码
@PostMapping("withDrawApply")
Result withdrawApply(@RequestBody Map<String,Object> param){
   Object amount = params.get("amount");
   toWithdrawApply(new BigDecimal(String.valueOf(amount));
}

Boolean  toWithdrawApply(BigDecimal amount){
      
    Map<String,Objct> param = new HashMap();
    param.put("amount", amount.multiply(new BigDecimal(100)).intValue());
    //TODO HTTP调用
    //此处大意就是将提现参数提交给支付机构;其他参数省略
    异步保存提现记录,此处提现记录中Record中的金额字段amount也取自:amount,保存的数据为19320.38
    return flag;
}

通过日志排查,在提交给第三方支付机构的参数日志中,amount金额变成了1932079。 所以总结下过程就是:用户提交金额19320.80,然后double经过String.value,转BigDeciaml,最后乘以100,少了一分钱。

第一时间怀疑是精度缺失问题,springboot中param接收到的amount实际类型为double类型,而浮点数在二进制计算中并不能真实表示该确切的值,因此其底层可能是19320.7999999999....来表示

但是我后续经过进行模拟处理操作,进行同jdk版本,cpu架构环境的参数进行调用处理,一直不能重现。所以很好奇这到底是和什么原因有关?如果是精度缺失按道理每次都会重现吧? 如果是精度缺失问题,正常的处理方式应该是什么呢? 期待各位大佬答疑。

相关推荐
庞轩px9 小时前
第1篇:Java内存模型(JMM)与volatile——并发编程的基石
java
是宇写的啊9 小时前
MyBatis-Plus
java·开发语言·mybatis
SamDeepThinking10 小时前
如何让订单系统和营销系统解耦
java·后端·架构
消失的旧时光-194310 小时前
线程池解决了什么?为什么还不够?(从线程到协程 · 第2篇)
java·大数据·数据库
jay神10 小时前
基于团队模式的C程序设计课程辅助教学管理系统
java·spring boot·vue·web开发·管理系统
薪火铺子10 小时前
Shiro权限框架深度解析
java·后端
1.14(java)10 小时前
Spring AOP核心概念与实战指南
java·后端·spring
亚历克斯神10 小时前
Java 安全最佳实践:构建安全的 Java 应用
java·spring·微服务
橙子圆12311 小时前
java之拦截器和适配器模式
java·开发语言
lifewange11 小时前
Claude Code可以安装在IDEA和Pycharm中么
java·pycharm·intellij-idea