今天在变量开发的过程中,遇到了这样的代码:
这段代码的意思是用BigDecimal的方式拿到整形的count与整形的totle,并将其做除法,然后保留三位小数,使用ROUND_HALF_UP进行四舍五入操作,最后再将其转换成double类型。
既然提到了BigDecimal,那就借此机会梳理一下有关浮点型数据计算,有关精度的那些坑。
在这里我突然想到了一个段子,那就是目前由于各种编程培训班的影响,培训班出来的学生的简历都是清一色的网上商城项目,那么如何判断应聘者是真的在工作中开发过有关商城的项目还是培训班流水线造假出来的工作经验呢?就问他在代码编写的过程中,对于物品订单价格,定义的类型是什么,说用的是double的,统一按培训班处理。为什么会这样说呢?
咱们看下面这个例子:
可以看到,结果和咱们想要得到的存在差别,别小看了这点差别,假如说只是算百分比,也许只是精度上的差别,影响不大,但如果是大量使用double来做订单金钱方面的计算。每天如果有个几百万订单,你想想得多少钱的帐对不上?
所以我们的解决办法就像项目中代码里看到,使用BigDecimal。但是BigDecimal就一点问题就没有了吗?请看以下的代码演示:
是不是使用BigDecimal就完事大吉了呢?咱们看下运行结果。
咱们发现,事情并没有想象的那么简单,运算结果还是不精确,只是精度更高了些。所以咱们要注意:
使用BigDecimal表示和计算浮点数,拜托一定要记得使用字符串的构造方法来初始化 BigDecimal
将其改成字符串以后,演示结果如下,就完美解决了这个问题。
那假如说,我们拿到的就是两个个double类型的,那我们应该怎么变成精确表达的BigDecimal呢?
我们发现存在多0了的情况,原因是BigDecimal有scale和precision的概念,前者的意思是表示小数点右边的位数,后者表示精度,也就是有效数字的长度。
技术参考:朱晔 贝壳金服资深架构师 Java业务开发常见错误