嗨!怎么样,工作还顺利吗?

编程开发

在Java中涉及到交易和金融货币的时候为什么不能用double、float来计算?使用BigDecimal解决

2020年05月26日 13:17:17 · 本文共 1,069 字阅读时间约 3分钟 · 4,014 次浏览
在Java中涉及到交易和金融货币的时候为什么不能用double、float来计算?使用BigDecimal解决

在Java中涉及到交易和金融货币的时候为什么不能用double、float来计算?在日常使用中double、float的浮点计算经常会出现一些意外的情况,因为二进制不能精确的表示大部分十进制的小数,今天就来讨论一下如何正确的在Java中进行小数计算。

先看案例

我们定义两个 float 变量,一个是1.0-0.9,我们预期是0.1;另一个是0.9-0.8,我们预期也是0.1,然后我们对这两个数进行打印和比较:

float a = 1.0F - 0.9F;
float b = 0.9F - 0.8F;
System.out.println("a: " + a);
System.out.println("b: " + b);
System.out.println("a == b: " + (a == b));
Float x = a;
Float y = b;
System.out.println("x.equals(y): " + x.equals(y));

运行结果是:

a: 0.100000024
b: 0.099999964
a == b: false
x.equals(y): false
java中double、float的浮点计算的精度损失

是不是超出了你的预期?在二进制的世界里小数不能很好的被表示,因为十进制小数在与二进制转换的时候会运行除法,而除法有的是除不尽的,这就造成了精度损失。

使用BigDecimal解决

java中提供了BigDecimal这个超大的类,用来存储浮点型,使用它可以处理二进制误差问题。我们使用BigDecimal改造上面的运算逻辑:

BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
BigDecimal c = new BigDecimal("0.8");
BigDecimal x = a.subtract(b); // 1.0 - 0.9
BigDecimal y = b.subtract(c); // 0.9 -0.8
System.out.println("x == y: " + (x == y)); // BigDecimal 是对象所以不能直接使用 == 进行比较
System.out.println("x.equals(y): " + x.equals(y));

运行结果是:

x == y: false
x.equals(y): true

使用BigDecimal的注意点

由于精度损失问题,使用new BigDecimal()的时候,我们只能使用参数为String的构造函数,也可以使用 BigDecimal.valueOf() 的方式,因为BigDecimal.valueOf()里面调用了Double.toString()方法,根据double实际表达能力对尾数进行了截断,我们可以查看一下JDK里面的源代码:

public static BigDecimal valueOf(double val) {
    // Reminder: a zero double returns '0.0', so we cannot fastpath
    // to use the constant ZERO.  This might be important enough to
    // justify a factory approach, a cache, or a few private
    // constants, later.
    return new BigDecimal(Double.toString(val));
}
商业用途请联系作者获得授权。
版权声明:本文为博主「任霏」原创文章,遵循 CC BY-NC-SA 4.0 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://www.renfei.net/posts/1003372
评论与留言

以下内容均由网友提交发布,版权与真实性无法查证,请自行辨别。

11

微信搜一搜:任霏博客