new BigDecimal(double)vs new BigDecimal(String)

时间:2015-04-14 16:19:04

标签: java bigdecimal double-precision

使用BigDecimal输入doubleBigDecimal并输入String时,似乎会出现不同的结果。

BigDecimal a = new BigDecimal(0.333333333);
BigDecimal b = new BigDecimal(0.666666666);

BigDecimal c = new BigDecimal("0.333333333");
BigDecimal d = new BigDecimal("0.666666666");

BigDecimal x = a.multiply(b);
BigDecimal y = c.multiply(d);

System.out.println(x);
System.out.println(y);

x输出为

0.222222221777777790569747304508155316795087227497352441864147715340493949298661391367204487323760986328125

而y是

0.222222221777777778

我说错误是因为双重不精确?但由于这是一个BigDecimal,它不应该是一样的吗?

4 个答案:

答案 0 :(得分:12)

  

我说这是因为双重不精确是错误的吗?

你是对的,这完全是因为double的不精确。

  

但由于这是BigDecimal,不应该是相同的吗?

不,它不应该。您创建new BigDecimal(0.333333333)时会引入错误,因为0.333333333常量已经嵌入了错误。那时你没有办法解决这个表征错误:到那时众所周知的马已经离开了谷仓,所以关门时已经太晚了。

另一方面,当您传递String时,十进制表示与字符串完全匹配,因此您得到的结果不同。

答案 1 :(得分:6)

是的,这是浮点错误。问题是文字0.3333333330.666666666在作为参数传递给BigDecimal之前被表示为双精度 - 值得注意的是,BigDecimal的构造函数需要一个double作为参数。

标准支持此项,即floating point literals default to double unless otherwise specified

答案 2 :(得分:4)

Java docs有它的答案。根据{{​​3}}

的Java文档
  

这个构造函数的结果可能有些不可预测。一   可能会假设在Java中编写新的BigDecimal(0.1)会创建一个   BigDecimal正好等于0.1(未缩放的值为1,带有   比例为1),但它实际上等于   0.1000000000000000055511151231257827021181583404541015625。这是因为0.1不能完全表示为双精度。

答案 3 :(得分:0)

当您以任何方式定义双变量时,在大多数情况下,它不会是您定义的值,而是最接近的二进制表示。你正在将一个double传递给构造函数,因此已经提供了那么小的不精确性。