关于金额的数据类型,以及元转分分转元之间这种转换,以及元和分的比较,我相信很多人都踩过坑。

反正我是踩过。

而且,昨天和今天又重重的踩了两脚。

代付查询接口,支付中心给溢+响应的报文里,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的更多相关文章

  1. '增量赋值(augmented assignment)', 多么痛的领悟!

    '增量赋值(augmented assignment)', 多么痛的领悟! 深刻理解x += a 与 x = x + a 的不同: 按理说上面的两条语句是等价的, 功能上完全一样的. 之所以说不同, ...

  2. php 3des加密 兼容JAVA 多么痛的领悟呀

    最近和别人做接口用到SOCKET TCP/IP方式 其中需要对账号和密码进行3DES加密 对方提供了一个加密比对的软件和JAVA的实现代码 并且给了我们一个长度为32位的密钥 这边需要用PHP来实现! ...

  3. Bellon(多么痛的领悟)

    尼玛  我今天刚刚知道什么是负权回路 任意相连的无向图之间都是回路!!! 囧了一天了,算是看出来了,渣比 A====B 则A能到B且B能到A,这就是一个回路.

  4. 在IIS中部署前后端应用,多么痛的领悟!

    目前手上的Web项目是前后端分离的,所以有时也会倒腾Vue框架. 前后端应用最终以容器形态.在k8s中部署, 为此我搭建了基于Gitlab flow的Devops流程. 在Devops实践中,容器部署 ...

  5. 数据倾斜是多么痛?spark作业调优秘籍

    目录视图 摘要视图 订阅 [观点]物联网与大数据将助推工业应用的崛起,你认同么?      CSDN日报20170703——<从高考到程序员——我一直在寻找答案>      [直播]探究L ...

  6. 【转】数据倾斜是多么痛?spark作业/面试/调优必备秘籍

    原博文出自于: http://sanwen.net/a/gqkotbo.html 感谢! 来源:数盟 调优概述 有的时候,我们可能会遇到大数据计算中一个最棘手的问题——数据倾斜,此时Spark作业的性 ...

  7. TreeView添加treeView1_NodeMouseClick----多么痛的领悟。。。

    TreeView添加treeView1_NodeMouseClick----多么痛的领悟... 1首先说一点,通过参考代码,已经实现了菜单项自动添加到TreeView控件的树视图了. 2.在移植(菜单 ...

  8. python学习第七讲,python中的数据类型,列表,元祖,字典,之元祖使用与介绍

    目录 python学习第七讲,python中的数据类型,列表,元祖,字典,之元祖使用与介绍 一丶元祖 1.元祖简介 2.元祖变量的定义 3.元祖变量的常用操作. 4.元祖的遍历 5.元祖的应用场景 p ...

  9. 002-Python3-基础语法-赋值、显示类型、数据类型[数值、字符串、列表、元祖、集合、字典]

    一.基础语法 参看地址:https://www.runoob.com/python3/python3-tutorial.html 基础数据类型 Python 中的变量不需要声明.每个变量在使用前都必须 ...

随机推荐

  1. Codeforces 219C - Color Stripe - [DP]

    题目链接:http://codeforces.com/problemset/problem/219/C 题意: 给你 $n$ 个方块排成水平一排,每个方块都涂上 $k$ 种颜色中的一种.要求对尽量少的 ...

  2. [No0000157].net core项目中拼音,excel,pdf处理库

    汉字转拼音 1. HxfPinYin public static class Pinyin { public static string ConvertEncoding(string text, En ...

  3. 【每日一题】 UVA - 213 Message Decoding 模拟解码+读入函数+阅读题

    题意:阅读理解难度一道比一道难orz.手摸了好久样例 题解: 读入:大循环用getline读入header顺便处理一下,  里面再写两重循环,外层一次读三个串,内层一次读num个串. 之后就查表,线性 ...

  4. href='#' 和 href='###'

    如果想定义一个空的链接,又不跳转到页面头部,可以写href="###". 详细解释就是'#' 是有特定意义的,如果 '#' 后有内容会被认为是一个标签而从页面找到相应标签跳转到该处 ...

  5. spark分组统计及二次排序案例一枚

    组织数据形式: aa 11 bb 11 cc 34 aa 22 bb 67 cc 29 aa 36 bb 33 cc 30 aa 42 bb 44 cc 49 需求: 1.对上述数据按key值进行分组 ...

  6. MySQL transaction

    MySQL transaction(数据库的事务) 数据库事务(Database Transaction),是指作为单个逻辑工作单元执行的一系列操作. 要么完全执行,要么完全地不执行. ACID 事务 ...

  7. [daily][tcpdump][bpf] 如何用tcpdump抓到一个分片包

    tcpdump -r web_185.pcap "ip[6:2] & 0x1fff != 0" tcpdump -r web_185.pcap "ip[6:2] ...

  8. 什么是restful api

    https://blog.csdn.net/laotianv5/article/details/81634997 什么是Restful API Restful API 从字面就可以知道,他是rest式 ...

  9. AndroidStudio_Button

    这里回顾一下Button的使用方法: 1.在page1.xml文件中定义一个按钮控件 <Button android:id="@+id/btn_textview" andro ...

  10. LeetCode 748 Shortest Completing Word 解题报告

    题目要求 Find the minimum length word from a given dictionary words, which has all the letters from the ...