java元转分使用浮点数精度丢失问题

2,140 阅读1分钟

应用场景

安卓将输入金额(元)转为(分)传给后端

错误代码及原因

因为在我的记忆中浮点数乘以100不会出问题(js给我留下的印象),所以写出了以下代码

public class PriceUtil {
    public static int stringYuan2intFen(String price) {
        return (int)(Float.parseFloat(price) * 100);
    }
}

错误场景,当price为0.59的时候运行会出现以下结果

Float.parseFloat("0.59") // 结果为0.59
Float.parseFloat("0.59") * 100  // 结果为58.999996,可以看出这一步出现了问题,不是预计的值
(int)(Float.parseFloat("0.59") * 100) // 由于上一步出现了问题,所以取整的结果为58

正确的方法

使用BigDecimal进行运算

public class PriceUtil {
    public static int stringYuan2intFen(String price) {
        return new BigDecimal(price).movePointRight(2).intValue();
    }
}

至此问题解决,以下是对自我的反思

反思

在用js的进行元转分未出现问题造成的惯性思维,以为大多数浮点数乘以100不会出问题,例如

0.1 * 100 // 10
0.2 * 100 // 20
0.3 * 100 // 30
0.59 * 100 // 59

可以看到js进行大多数元转分计算是没有问题的,然后我尝试了更多的数字,果然出了问题,例如

36.62 * 100 // 3661.9999999999995
0.1 * 101 // 10.100000000000001
0.2 * 101 // 20.200000000000003
0.3 * 101 // 30.299999999999997
0.59 * 101 // 59.589999999999996

可以看到所有的结果都和预期有出入 惯性思维害死人呀~

js小数精度解决方案

使用 bigNumber.js 库