java BigDecimal在转换为浮点/从浮点转换时不保留舍入值
我有一个函数,它使用BigDecimal将一个浮点数舍入到n位数。设置刻度
private float roundPrice(float price, int numDigits) {
BigDecimal bd = BigDecimal.valueOf(price);
bd = bd.setScale(numDigits, RoundingMode.HALF_UP);
float roundedFloat = bd.floatValue();
return roundedFloat;
}
public void testRoundPrice() {
float numberToRound = 0.2658f;
System.out.println(numberToRound);
float roundedNumber = roundPrice(numberToRound, 5);
System.out.println(roundedNumber);
BigDecimal bd = BigDecimal.valueOf(roundedNumber);
System.out.println(bd);
}
输出:
0.2658
0.2658
0.26579999923706055
如何防止BigDecimal在舍入值末尾添加所有这些额外数字
注意:我无法执行以下操作,因为我无法访问api调用函数中的位数
System.out.println(bd.setScale(5, RoundingMode.CEILING));
# 1 楼答案
我决定修改我的程序,在我的对象中使用BigDecimal作为我的财产价格的基本类型,而不是float类型。虽然一开始很棘手,但从长远来看,它肯定是更清洁的解决方案
# 2 楼答案
反过来说
BigDecimal
在告诉你真相。0.2657999923706055更接近float
在舍入前后一直获得的值。作为二进制而不是十进制数的float
不能精确地容纳0.2658。实际上,0.26579999237060546875是我们能得到的最接近的打印浮点时,不会得到完整值。会发生一些舍入,因此尽管
float
具有上述值,但您只会看到0.2658
当您从
float
创建一个BigDecimal
时,实际上是首先转换为double
(因为这是BigDecimal.valueOf()
接受的)。double
的值与float
的值相同,但打印为0.2657999923706055,这也是BigDecimal
获得的值如果希望一个
BigDecimal
具有float
的打印值,而不是其中的确切值或接近值,则以下操作可能有效:输出:
但是,您可能会对其他值感到惊讶,因为
float
没有那么高的精度编辑:您正在有效地转换
float
->double
->String
->BigDecimal
强>达伍德·伊本·卡里姆(Dawood ibn Kareem)的这些富有洞察力的评论让我进行了一些研究:
那么到底发生了什么:
float
在四舍五入前后的内部值均为0.26579999237060546875李>float
传递给BigDecimal.valueOf(double)
时,您实际上是在转换float
->double
->String
->BigDecimal
。double
的值与float
的值相同,为0.26579999237060546875李>String
的转换将稍微舍入到"0.26579999923706055"
李>BigDecimal
得到的值为0.2657999923706055,这是您看到和询问的值李>从
BigDecimal.valueOf(double)
的文档中:链接