我正在尝试实现一个新的等级舍入到BigDecimal类,我得到一个可能的错误,我可能做错了。下面的代码暴露了我的问题:
public static void main(String[] args) throws IOException {
BigDecimal valDouble = new BigDecimal(0.35);
valDouble = valDouble.setScale(1, BigDecimal.ROUND_HALF_UP);
System.out.println(valDouble.doubleValue()); // prints 0.3
BigDecimal valString = new BigDecimal(new String("0.35"));
valString = valString.setScale(1, BigDecimal.ROUND_HALF_UP);
System.out.println(valString.doubleValue()); // prints 0.4
}
我的疑问是,对于double和String构造函数,BigDecimal是不同的吗?
我无法理解这个'bug',至少,我只是用一个简单的字符串concat来“解决”它,如下所示:
BigDecimal valDouble = new BigDecimal("" + 0.35);
知道可能导致这种奇怪行为的原因是什么?
答案 0 :(得分:7)
这不是错误。作为双字面值的0.35表示不完全等于0.35的值;它可能像0.349999995之类的东西。所以它结束了。
String构造函数允许您使用“0.35”精确指定0.35,然后向上舍入。
此处不要使用double
构造函数;当它足够重要使用BigDecimal
时,你需要远离浮点土地。
答案 1 :(得分:3)
您无需猜测0.35代表什么
BigDecimal valDouble = new BigDecimal(0.35);
System.out.println(valDouble);
打印
0.34999999999999997779553950749686919152736663818359375
这将向下舍入到小数点后1位为0.3
您无需转换为字符串,可以使用valueOf
BigDecimal valDouble = BigDecimal.valueOf(0.35);
System.out.println(valDouble);
打印
0.35
要将一半小数舍入到小数点后一位,您可以使用
double d = 0.35;
double d1 = Math.round(d * 10) / 10.0;
System.out.println(d1);
打印
0.4
答案 2 :(得分:0)
0.35已经不精确,成为FP的二进制基数。使用新的BigDecimal(“0.35”),这是精确的,因为十进制基数。