太阳城娱乐网最快登入 0
太阳城娱乐网最快登入

我的帖子

个人中心

设置

  发新话题
本文来源:http://www.2233122.com/news_17173_com/

太阳城娱乐网最快登入,  上厕所出来,我到洗手池洗手,看到男厕所边上有个穿绿色军大衣的男子,也没在意。  习近平指出,军队规模结构和力量编成改革的总体思路是,以党在新形势下的强军目标为引领,贯彻新形势下军事战略方针,坚持政治建军、改革强军、依法治军,聚焦备战打仗,着眼于维护国家主权、安全、发展利益,有效应对各战略方向和重大安全领域现实威胁,按照调整优化结构、发展新型力量、理顺重大比例关系、压减数量规模的要求,推动我军由数量规模型向质量效能型、由人力密集型向科技密集型转变,部队编成向充实、合成、多能、灵活方向发展,构建能够打赢信息化战争、有效履行使命任务的中国特色现代军事力量体系。经西藏自治区食品药品检验所检验,发现标示为金诃藏药股份有限公司和西藏金珠雅砻藏药有限责任公司生产的批号分别为20150407和131001的二十五味珊瑚丸检出808猩红。  中国保险资产管理业协会执行副会长兼秘书长曹德云表示,2015年以来,低利率环境持续,固定收益类资产投资收益率大幅下降,而保费规模持续快速增长,成本居高不下,使保险资金配置承受较大压力,客观上促使其将投资视角转向权益类相关资产。

  中美搏击产业发展论坛由北京无极道体育产业发展有限公司、世界格斗协会、世界摔角联合会联合多家机构主办,并得到国家体育总局、北京市体育总会等方面的支持。中共中央政治局委员、国务院副总理刘延东出席会议并讲话。6月20日,Shibor隔夜利率大幅飙升578.40个基点,利率首次超过10%,达到13.4440%。适时地牵手和触摸会让两人之间亲匿的温度更足够,偶尔往往小动作的亲匿和拥抱会改善这样的关系。

”和英子断了来往后,小赵过得很颓废,做什么都没有心思,介绍人看不下去,偷偷告诉小赵,其实英子是很喜欢他的,只是她父母不想把女儿嫁到遥远的云南,怕女儿在异乡会吃苦。11月美国犹他州的一个国际会议公布了超级计算机500强排名。杨先生向信网提供了他的收费收据,其中还有一张总共1900元费用的结清单据,既然查无杨先生的诊疗记录,这些单据又从何而来是否工作人员肯定系统中无记录,就说明该患者没有在即墨虹桥医院诊治过对此,工作人员始终未说明。但是,在一片惊愕之中,不少媒体反应过速,甚至将朴槿惠总统的做好下台准备直接解读为宣告下台,并且将谈话内容的微妙之处也翻译得比较令人误会。

前段时间和某银行合作共同开发了适合我们的一套支付系统。最近,我们对账发现某些订单始终都对不齐。银行的下单金额与对账金额始终少了1分钱。
这就奇怪了,如果这种异常订单一多就是少了很多钱。在涉及钱的金融领域,这是个很谨慎严肃的问题。
我们跟银行排查发现了问题的原因,也就是我今天想聊的关于技术上的东西:double精度的丢失问题。
1问题复现
我们先举个简单的例子
  • double result = 1.0 - 0.9;
这段代码中result等于多少?0.1么?如果执行代码的话,分分钟打脸。


double精度丢失问题


2背后原理
无论是我们本文提到的double,还是float,都是浮点数。
在计算机科学中,浮点(英语:floating point,缩写为FP)是一种对于实数的近似值数值表现法,由一个有效数字(即尾数)加上幂数来表示,通常是乘以某个基数的整数次指数得到。以这种表示法表示的数值,称为浮点数(floating-point number)。
计算机使用浮点数运算的主因,在于计算机使用二进位制的运算。
例如:4÷2=2,4=100(二进制)、2=010(二进制)。在二进制中除以2相当于退一位数。
那么1.0÷2=0.5=0.1(二进制)也就是1/2,依此类推二进制的0.01(二进制)就是十进制 1/(2^2) = 1/4 = 0.25。
上面看到的1、0.5、0.25那都是可以转换成二进制的小数,如十进制的0.1,就无法用二进制准确的表示出来。因此只能使用近似值的方式表达。
比如,我们尝试着把10进制的0.1转化成二进制试试,步骤如下:
  • 0.1*2=0.2……0——整数部分为“0”。整数部分“0”清零后为“0”,用“0.2”接着计算。
  • 0.2*2=0.4……0——整数部分为“0”。整数部分“0”清零后为“0”,用“0.4”接着计算。
  • 0.4*2=0.8……0——整数部分为“0”。整数部分“0”清零后为“0”,用“0.8”接着计算。
  • 0.8*2=1.6……1——整数部分为“1”。整数部分“1”清零后为“0”,用“0.6”接着计算。
  • 0.6*2=1.2……1——整数部分为“1”。整数部分“1”清零后为“0”,用“0.2”接着计算。
  • 0.2*2=0.4……0——整数部分为“0”。整数部分“0”清零后为“0”,用“0.4”接着计算。
  • 0.4*2=0.8……0——整数部分为“0”。整数部分“0”清零后为“0”,用“0.8”接着计算。
  • 0.8*2=1.6……1——整数部分为“1”。整数部分“1”清零后为“0”,用“0.6”接着计算。
  • 0.6*2=1.2……1——整数部分为“1”。整数部分“1”清零后为“0”,用“0.2”接着计算。
  • 0.2*2=0.4……0——整数部分为“0”。整数部分“0”清零后为“0”,用“0.4”接着计算。
  • 0.4*2=0.8……0——整数部分为“0”。整数部分“0”清零后为“0”,用“0.2”接着计算。
  • 0.8*2=1.6……1——整数部分为“1”。整数部分“1”清零后为“0”,用“0.2”接着计算。
  • ……
可以发现,这个过程是除不尽的,除出了一个无限循环小数:二进制的 0.0001100110011…
那么,如何在计算机中表示这个无限不循环的小数呢?只能考虑按照不同的精度保理不同的位数。
我们知道float是单精度的,double是双精度的。不同的精度,其实就是保留的有效数字位数不同,保留的位数越多,精度越高。
所以,浮点数在Java中是无法精确表示的,因为大部分浮点数转换成二进制是一个无限不循环的小数,只能通过保留精度的方式进行近似表示。
在《阿里巴巴Java开发手册》中其实也有着明确的规定,说明了小数类型禁止使用float或者double来表示。(虽然这条是Mysql相关规则,但是Java代码同样适用。)


3问题引申
我们现在基本已经知道了double的精度问题是什么问题。
在实际的订单交易过程中,出现这个问题的更多场景是金额单位元与分的转换。银行给你的单位是元,你自己的运算是分;前端输入是元,计算是分等等。
举个例子:用户下了一笔64.6元的订单,你在需要转换成分。如果直接除以100,你会发现计算出来的分始终是6459,少1分钱。


金额丢失1分问题


4解决方式
1)使用BigDecimal
为了解决这种浮点小数进度丢失问题,java提供了一种计算方式BigDecimal。


BigDecimal


这样就可以了么? 不是,这样能解决大部分问题,假如其他系统或语言不支持BigDecimal呢。当我们无法解决这个问题的时候,我们需要做的是想办法规避这个问题带来的影响。
2)以分为单位,Long为数据结构存储
目前我们某些核心系统在金额传输的过程和存储中还是以元存储浮点数。导致低于10元的订单计算利息费率的时候,无法计算清楚,使得我们的业务服务在处理这些问题头疼死了。
整数与整数的计算,就没有这些精度丢失问题。Long取值范围(9223372036854775807)完全够用。
3)除不尽怎么办
对于除法,始终会产生除不尽的情况怎么办?有个词叫轧差
什么意思呢?举个简单例子。假如现在需要把10元分成3分,如果是10除以3这么除,会发现为3.33333无穷尽的3。这些数字完全无法在程序或数据库中进行精确的存储。
简单理解就是,当除不尽或需去除小数点的时候,前面的n-1笔(这里n=3)做四舍五入。最后一笔做兜底(总金额减去前面n-1笔之和)。这样保证总金额的不会丢失。
这里我们的具体应用场景是用户使用了现金券,然后有部分退款,计算应退本金的问题。现金券的处理又是一大篇文章,这里以后有机会再介绍。
5总结能用Long不用浮点数存储。
前后端传输金额(元)的时候,请使用字符串,不要使用浮点数。
浮点数运算请使用BigDecimal。
实在无法除尽,可以考虑通过轧差的方式解决。
double精度不是坑,是个容易忽视的巨坑,小小经验希望对大家有所帮助,谨慎对待。>-<
关于银行1分差的问题,等待银行修复,历史订单做调账处理,哈哈哈哈哈。
太阳城娱乐网最快登入本帖最近评分记录
  • super小邪 无忧币 +10 感谢分享~ 2019-2-18 09:25






太深奥










好详细哦,没看懂,但是看完了



最后一笔兜底我用过,以前设计促销组合功能,涉及单品退货,所以整单金额作单价比拆分后分摊每个商品,最后一个商品分摊金额就是兜底。



厉害了



引用:
原帖由 七彩极 于 2019-02-02 22:41 发表
程序员是如何神不知鬼不觉的弄丢银行1分钱的?
*




学习了



引用:
原帖由 七彩极 于 2019-02-02 22:41 发表
程序员是如何神不知鬼不觉的弄丢银行1分钱的?
处理小数精确问题




厉害



学到了   厉害



不学这个,但是应该是倒轧,好像要比轧差好。



51CTO论坛有移动端啦!扫码下载体验就送月会员哦!
提示: 作者被禁止或删除 内容自动屏蔽
插眼




这么脑残的问题别在这问了



好复杂 看着有点头晕



体育用品-www.verodillan.com
‹‹ 上一贴:新入职公司IT团队需要扩充,是招聘新人,还是拉来以前的下 ...   |   下一贴:有职称证需要找单位的吗 ››
  发新话题
快速回复主题
关于我们 | 诚聘英才 | 联系我们 | 网站大事 | 友情链接 |意见反馈 | 网站地图
Copyright©2005-2020 太阳城娱乐网最快登入 www.2233122.com
本论坛言论纯属发布者个人意见,不代表51CTO网站立场!如有疑义,请与管理员联系:bbs@太阳城娱乐网最快登入 www.2233122.com
申博登陆网址 太阳城申博官方直营网 申博游戏手机版登入 申博138怎么登入不了 sun138.comwww 申博游戏平台登入
菲律宾申博官方直营网 菲律宾申博太阳城娱乐 申博开户直营网 www.1111msc.com 太阳城赌场太阳城直营网 申博亚洲太阳城娱乐直营网
申博微信支付充值 申博手机客户端下载登入 申博登录不了 申博网址 申博138线上娱乐直营网 www.tyc599.com