首页 > 解决方案 > 为什么 BigDecimal 在 Java 中返回我的大 double 的近似值?

问题描述

我想对我的大双精度数进行舍入,所以我决定做的第一件事就是通过以下方式将其转换为 BigDecimal。

    BigDecimal amount = BigDecimal
        .valueOf(getAmount())
        .setScale(2, RoundingMode.HALF_UP);
    System.out.println(amount);

在我的示例中,getAmount()返回123456789123123424113.31.

因此,我希望我的代码段打印出完全相同的值。

相反,我得到以下值:

123456789123123430000.00

有人可以解释为什么 BigDecimal 返回我的双精度值的近似值吗?

标签: java

解决方案


在我的示例中,getAmount()返回123456789123123424113.31.

不,不是的。这不是 adouble可以准确表示的值。

您可以使用以下代码轻松验证:

double d = 123456789123123424113.31d;
System.out.println(d);

哪个输出

1.2345678912312343E20

此值具有最少的位数,可将其与任何其他double值唯一区分开来。这意味着 中没有更多相关的数字double将值转换为BigDecimal.

虽然整数数据类型,例如longandint可以精确地表示其范围内的每个(整数)值,但对于浮点数则不能这样说:它们可以表示的值范围很广,但代价是不能够表示范围内的每个可能值。实际上,浮点数可以表示的位数是有限的(大约 16 个十进制数字double和大约 7 个十进制数字float)。其他一切都将被切断。

如果您需要任意精度,那么类似的东西BigDecimal会有所帮助:它将分配尽可能多的内存来保存所有数字(或根据您的规范四舍五入,如果需要),使其更复杂但也更强大。

BigDecimal bd = new BigDecimal("123456789123123424113.31");
System.out.println(bd);

将打印

123456789123123424113.31

确保不要BigDecimal从一个double值初始化,因为即使那样你也只会得到截止值。


推荐阅读