Java中BigDecimal转换大型double类型数值为何返回近似值?
问题原因说明
你遇到的问题本质是double类型本身的精度限制导致数值先发生了失真,和BigDecimal的处理逻辑无关。
具体原因拆解
- IEEE 754标准的64位双精度浮点数(也就是Java里的double类型),只有53位二进制有效尾数,换算成十进制大约只有15~17位有效数字。你用到的数值
123456789123123424113.31仅整数部分就有21位,已经远远超出了double能精确表示的范围,这个值在getAmount()作为double返回的时候,就已经被舍入为double能表示的最接近的近似值,原始的低位数字和小数部分已经丢失了。 - 你调用的
BigDecimal.valueOf(double)方法,本质是先把double的字符串表示转为BigDecimal,此时输入的double本身已经是失真的近似值,后续无论怎么设置舍入规则和保留位数,都无法找回已经丢失的原始数值信息,因此最终输出的是近似结果。
正确的实现方案
- 优先修改
getAmount()的返回类型,直接返回BigDecimal,从数值产生的源头就避免使用double存储,杜绝精度损失。 - 如果无法修改
getAmount()的逻辑,需要确保原始数值以字符串形式传递,使用字符串构造BigDecimal即可得到完全精确的结果:
// 注意参数是字符串类型,不是double BigDecimal amount = new BigDecimal("123456789123123424113.31") .setScale(2, RoundingMode.HALF_UP); System.out.println(amount);
内容的提问来源于stack exchange,提问作者ptk
相关产品推荐
相关产品推荐

