为什么不该用 Double 表示金额及解决方案
当前位置:点晴教程→知识管理交流
→『 技术文档交流 』
众所周知,double 和 float 这些浮点数其实是不精确的。 比如 0.1 + 0.2 并不等于 0.3,而是等于 0.30000000000000004——这也一度成为程序员圈子里的经典梗。所以用浮点数表示金额这种需要精确计算的数值,是会出现精度丢失问题的。
再看一个更实际的例子,假设你在做一个电商系统的金额计算:
你看,原本应该是 1.8 的结果,却变成了 1.7999999999999998。如果这是真实的订单金额,那可就出大问题了 为什么会精度丢失为什么会有这种精度丢失呢?因为计算机底层都是用二进制存储的,但并不是所有十进制数都能用二进制精确表示。各位有兴趣的话可以试着算一下 0.1 的二进制是多少,算出来可以在评论区分享一下。 算了一会你可能会发现:这怎么算不完?没错,出现了无限循环的情况——(0.1)₁₀ = (0.000110011001100...)₂ 像这种情况,计算机就没办法用二进制精确表示 0.1 了。 而 double 类型在 Java 中占 64 位,按照 IEEE 754 标准,其中 1 位是符号位,11 位是指数位,52 位是尾数位。当遇到无限循环的二进制小数时,只能截断保存,这就导致了精度丢失。 BigDecimal在 Java 中,无论是单精度还是双精度,表示的都是近似值。 为了表示精确的小数值,Java 提供了 举个例子,数字 123.45 在 BigDecimal 中:
实际值就是:12345 × 10⁻² = 123.45 用 BigDecimal 来处理刚才的金额计算:
这下结果就对了 equals 的坑在 BigDecimal 中不能用 equals 方法做等值比较,因为 equals 会同时比较无标度值和标度这两个内容。
我们都知道 0.1 和 0.10 在数值上是相等的,但 equals 的结果却是 false。这是因为:
虽然值相同,但它们的标度不同,所以 equals 返回 false。 compareTo比较 BigDecimal 大小时应该使用 compareTo 方法,返回值为 1、-1、0,分别代表大于、小于、等于。
创建 BigDecimal 的正确姿势创建 BigDecimal 时,建议使用 String 类型的构造方法,也就是
如果你用了 还有一个更方便的方法:
常用的 BigDecimal 运算
注意除法操作时,如果不指定精度,遇到除不尽的情况会抛出 总之,涉及金额计算时,千万别图省事用 double,老老实实用 BigDecimal 才是王道。 转自https://www.cnblogs.com/longlonglong777/p/19133663 该文章在 2025/10/11 8:33:59 编辑过 |
关键字查询
相关文章
正在查询... |