多么痛的领悟---关于RMB数据类型导致的元转分分转元的bug
关于金额的数据类型,以及元转分分转元之间这种转换,以及元和分的比较,我相信很多人都踩过坑。
反正我是踩过。
而且,昨天和今天又重重的踩了两脚。
代付查询接口,支付中心给溢+响应的报文里,amount的单位是分,数据类型是int,这无可厚非,非常合理。
昨天,负责溢+代付的中威反映,有一笔单子返回的是代付成功的状态,但因校验支付中心返回的代付金额与溢+存储的代付金额不一致,而导致溢+未能更新代付单的状态。
经查支付中心,DB里代付金额字段的数据类型是double,单位是元,程序里对应的pojo也把代付金额的属性设置为double。
出问题的那一单的代付金额是1049.11,而最终响应给溢+的代付金额却是104910。显然,这会致使溢+校验代付金额失败。
如下是赋值代码:
responseModel.setAmount((int) (record.getPayMoney() * )); //元转分
测试发现,Double的1049.11经这么转换后,果然是104910。拍拍脑袋,这自然是double的数据精度的问题了。又进一步测试了几个临近的数:1049.10→104909,1049.11→104910,1049.12→104911,并且1049.13可以正常转换为104913
于是,尝试将代付金额的数据类型改为float,经测试,改为float后以上数据转换正常。
之前做结算系统时也遇到过类似问题。由于手头工作较多,这里不再继续了解double和float的区别了。
走申请,上线!
到了今天下午,溢+那边又反映:又存在了3笔代付单,支付中心返回了错误的代付金额。
/汗
其中一笔的代付金额是20.38,支付中心响应给溢+的值是2037。另外还有两笔,151.4→15139;32.85→3284
不能再那么敷衍了。
同事说之前项目用的都是BigDecimal。我将信将疑,写了个测试用例,来看看到底BigDecimal与Double/Float取值有哪些不同:


通过看测试数据,发现,无论BigDecimal/Double/Float,其intValue()方法,返回的值都是整数部分, 不会像Math.round()那样做进行四舍五入。因为我上面贴出来的那条元转分的语句,(int) (record.getPayMoney() * 100)等价于(record.getPayMoney() * 100).intValue(),所以,转换得到的分就会出现因浮点型数据精度而导致的少1分的小概率情况。
那天有同事问我为什么interface的方法不用public修饰,我从OO角度跟他解释了原因。 不琢磨,一些简单的问题也搞不清。而我今天,也同样遭遇了他的那种情况。
最后,因为支付中心是从.net翻版的,我打开visualstudio,发现,.net给代付金额定义的类型也是decimal。
于是,果断将代付金额的数据类型重构为BigDecimal。
多么痛的领悟---关于RMB数据类型导致的元转分分转元的bug的更多相关文章
- '增量赋值(augmented assignment)', 多么痛的领悟!
'增量赋值(augmented assignment)', 多么痛的领悟! 深刻理解x += a 与 x = x + a 的不同: 按理说上面的两条语句是等价的, 功能上完全一样的. 之所以说不同, ...
- php 3des加密 兼容JAVA 多么痛的领悟呀
最近和别人做接口用到SOCKET TCP/IP方式 其中需要对账号和密码进行3DES加密 对方提供了一个加密比对的软件和JAVA的实现代码 并且给了我们一个长度为32位的密钥 这边需要用PHP来实现! ...
- Bellon(多么痛的领悟)
尼玛 我今天刚刚知道什么是负权回路 任意相连的无向图之间都是回路!!! 囧了一天了,算是看出来了,渣比 A====B 则A能到B且B能到A,这就是一个回路.
- 在IIS中部署前后端应用,多么痛的领悟!
目前手上的Web项目是前后端分离的,所以有时也会倒腾Vue框架. 前后端应用最终以容器形态.在k8s中部署, 为此我搭建了基于Gitlab flow的Devops流程. 在Devops实践中,容器部署 ...
- 数据倾斜是多么痛?spark作业调优秘籍
目录视图 摘要视图 订阅 [观点]物联网与大数据将助推工业应用的崛起,你认同么? CSDN日报20170703——<从高考到程序员——我一直在寻找答案> [直播]探究L ...
- 【转】数据倾斜是多么痛?spark作业/面试/调优必备秘籍
原博文出自于: http://sanwen.net/a/gqkotbo.html 感谢! 来源:数盟 调优概述 有的时候,我们可能会遇到大数据计算中一个最棘手的问题——数据倾斜,此时Spark作业的性 ...
- TreeView添加treeView1_NodeMouseClick----多么痛的领悟。。。
TreeView添加treeView1_NodeMouseClick----多么痛的领悟... 1首先说一点,通过参考代码,已经实现了菜单项自动添加到TreeView控件的树视图了. 2.在移植(菜单 ...
- python学习第七讲,python中的数据类型,列表,元祖,字典,之元祖使用与介绍
目录 python学习第七讲,python中的数据类型,列表,元祖,字典,之元祖使用与介绍 一丶元祖 1.元祖简介 2.元祖变量的定义 3.元祖变量的常用操作. 4.元祖的遍历 5.元祖的应用场景 p ...
- 002-Python3-基础语法-赋值、显示类型、数据类型[数值、字符串、列表、元祖、集合、字典]
一.基础语法 参看地址:https://www.runoob.com/python3/python3-tutorial.html 基础数据类型 Python 中的变量不需要声明.每个变量在使用前都必须 ...
随机推荐
- Windows环境下安装Linux
怎样实现在现有的Windows系统上安装Linux,实现双系统启动
- POJ 1854 - Evil Straw Warts Live
Description A palindrome is a string of symbols that is equal to itself when reversed. Given an inpu ...
- React 60S倒计时
React 60S倒计时 1.设置状态: 2.函数主体: 3.应用: 4..效果图:
- MySQL命令:约束
约束是一种限制,它通过对表的行或列的数据做出限制,来确保表的数据的完整性.唯一性 约束分类: 约束类型与关键字: 主键 PRIMARY KEY 默认值 DEFAULT 唯一 UN ...
- HTML响应状态码
https://www.restapitutorial.com/httpstatuscodes.html
- AngularJs 常用指令标签
1.ng-app:告诉Angular他应该管理页面的那一部分,可以放在html元素上也可以放在div等标签上 例:<html ng-app="problem"> 2.n ...
- Flink – CEP NFA
看看Flink cep如何将pattern转换为NFA? 当来了一条event,如果在NFA中执行的? 前面的链路,CEP –> PatternStream –> select –> ...
- 知乎改版api接口之scrapy自动登陆
最近使用scrapy模拟登陆知乎,发现所有接口都发生变化了,包括验证码也发生了很大变化,通过抓包分析,记录下改版后的知乎模拟登陆,废话不多说,直接上代码,亲测有效 # -*- coding: utf- ...
- CF865D Buy Low Sell High 贪心
正解:贪心 解题报告: 传送门! 这题首先有个很显然的dp,太基础了不说QAQ 然后考虑dp是n2的,显然过不去,所以换一个角度 然后发现这题和普通的dp的题有什么不同呢?就它这儿是一天只能买一支股, ...
- 一步步搭建 Spring Boot maven 框架的工程
摘要:让Spring应用从配置到运行更加快速,演示DIY Spring Boot 框架时,如何配置端口号,如何添加日志. Spring Boot 框架帮助开发者更容易地创建基于Spring的应用程序和 ...