为什么BigDecimal在Java中返回我的大双精度的近似值?
我想舍入我的大双精度数,所以我决定做的第一件事是按以下方式将其转换为 BigDecimal。
BigDecimal amount = BigDecimal
.valueOf(getAmount())
.setScale(2, RoundingMode.HALF_UP);
System.out.println(amount);
在我的示例中,getAmount()返回123456789123123424113.31.
因此,我希望我的代码片段打印出完全相同的值。
相反,我得到以下值:
123456789123123430000.00
有人可以解释为什么 BigDecimal 返回我的 double 的近似值吗?
回答
在我的示例中,
getAmount()返回123456789123123424113.31.
不,不是的。那不是 adouble可以准确表示的值。
您可以使用以下代码轻松验证:
double d = 123456789123123424113.31d;
System.out.println(d);
double d = 123456789123123424113.31d;
System.out.println(d);
哪些输出
该值具有最少的位数,可以唯一地将其与任何其他double值区分开来。这意味着double. 你已经失去了精度之前的值转换为BigDecimal。
虽然诸如long和 之类的整数数据类型int可以精确地表示其范围内的每个(整数)值,但对于浮点数却不能这样说:它们可以表示的值范围很广,但代价是不能够表示范围内的每个可能的值。实际上,浮点数可以表示的位数是有限的(大约 16 位十进制数字double和大约 7 位十进制数字)float)。其他一切都将被切断。
如果您需要任意精度,那么类似的东西BigDecimal会有所帮助:它将根据需要分配尽可能多的内存来保存所有数字(或根据您的规范进行舍入,如果需要),使其更复杂但也更强大。
BigDecimal bd = new BigDecimal("123456789123123424113.31");
System.out.println(bd);
将打印
1.2345678912312343E20
确保不要BigDecimal从double值初始化,因为即使那样你也只能得到截止值。
- @p4t: use `BigDecimal` all throughout your calculation and never convert anything to a `double` (not even for intermediate results). Also make sure those `BigDecimal` are not **initialized** from `double` values (use the `String` constructor if you need decimal points).