在Java中涉及到交易和金融货币的时候为什么不能用double、float来计算?使用BigDecimal解决
2020年05月26日 13:17:17 · 本文共 1,069 字阅读时间约 3分钟 · 4,590 次浏览在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
是不是超出了你的预期?在二进制的世界里小数不能很好的被表示,因为十进制小数在与二进制转换的时候会运行除法,而除法有的是除不尽的,这就造成了精度损失。
使用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://blog.renfei.net/posts/1003372
版权声明:本文为博主「任霏」原创文章,遵循 CC BY-NC-SA 4.0 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.renfei.net/posts/1003372
相关推荐
猜你还喜欢这些内容,不妨试试阅读一下
热评文章
- 前后端分离项目接口数据加密的秘钥交换逻辑(RSA、AES)
- OmniGraffle 激活/破解 密钥/密匙/Key/License
- 人大金仓 KingbaseES V8 R3 安装包、驱动包和 License 下载地址
- Parallels Desktop For Mac 16.0.1.48911 破解版 [TNT]
- Redis 未授权访问漏洞分析 cleanfda 脚本复现漏洞挖矿
- CleanMyMac X 破解版 [TNT] 4.6.0
- OmniPlan 激活/破解 密钥/密匙/Key/License
- Sound Control 破解版 2.4.2
- Parallels Desktop For Mac 15.1.4.47270 破解版 [TNT]
- Parallels Desktop For Mac 16.0.0.48916 破解版 [TNT]
热文排行
- 博客完全迁移上阿里云,我所使用的阿里云架构
- 微软确认Windows 10存在bug 部分电脑升级后被冻结
- 大佬们在说的AQS,到底啥是个AQS(AbstractQueuedSynchronizer)同步队列
- 比特币(BTC)钱包客户端区块链数据同步慢,区块链数据离线下载
- Java中说的CAS(compare and swap)是个啥
- 小心免费主题!那些WordPress主题后门,一招拥有管理员权限
- 强烈谴责[wamae.win]恶意反向代理我站并篡改我站网页
- 讨论下Java中的volatile和JMM(Java Memory Model)Java内存模型
- 新版个人网站 NEILREN4J 上线并开源程序源码
- 我站近期遭受到恶意不友好访问攻击公告