解决java/javascript执行金额计算时出现的浮点数精度丢失

问题描述

最近在开发时出现了一项非常尴尬的事情,那就是在购买服务时,很容易出现下面这种情况:

这里可以清楚的看到,已经出现了精度缺失的现象。相信有的人可能觉得,不就是多出了那么一个0.0000...3吗?直接把它删了不就好了,这是一种错误的选法,因为你根本就不知道下一次运算是多了还是少,而且这也是有着比较大风险的,下面介绍两种常用的解决方法:

这里分别提供java端与javascript端两种解决浮点数精度的方法

1、java解决浮点数精度问题

在java中,有着一个专门的类进行浮点数的计算,那就是BigDecimal。在使用该类时,我们应当确保该对象本身不为null。与此同时,该类还附带有舍入模式,但是在金额的计算上,我们最好还是不要使用其舍入模式。我们可以使用该类进行浮点数的计算,此处我使用的是减法运算,具体代码如下:

BigDecimal userMoney= BigDecimal.valueOf(user.getMoney());
BigDecimal indentMoney= BigDecimal.valueOf(indent.getMoney());
Double newMoney=userMoney.subtract(indentMoney).doubleValue();
userMapper.changeMoneyByAccount(indent.getUserId(),newMoney);//更新用户余额

在这我只用到了减法运算,如果需要乘法运算等,则需要用到该类的其他方法。其实稍微看一下,就能看出来,BigDecimal类似乎就是一个包装类,包装后进行运算,再通过其.doubleValue()方法进行取值。

大家在进行有关小数的乘除,金额计算等一定要使用上面这个包装类,因为谁也不想自己的余额不稳定吧。

2、javascript解决浮点数精度问题

大家需要注意的是,精度丢失问题不仅仅在java端出现,在javascript上也会出现相同的问题,但问题是,javascript可没有封装好的BigDecimal类供我们使用,那我们应当如何防止精度丢失呢?

答案就是将浮点数转换为整数进行运算,在运算过后再转换为小数,具体代码如下:

wx.setStorageSync('money', (wx.getStorageSync('money')*100-(this.data.service.money*this.data.coupon.discount-this.data.coupon.reduceMoney)*100)/100.0)

在这里可以看见,我们对于数据先乘以100转换为整数,完成运算后,再除以100.0换算回小数。注意,这里我除以的是100.0而非100。我也不知道这两个再js的区别大不大,但是在C语言上,这两个数会影响你最后求出来的是小数还是整数,所有这里除以100.0.

总结

无论在任何一门语言内,都有可能出现浮点数丢失、数据溢出等问题,我们在日常生活中应当多加小心才是。同时,对于浮点数丢失,多数出现于小数的乘除运算,当然,这也并不意味着加减就不会出现浮点数丢失的问题。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

易烊子豪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值