new BigDecimal(double)vs new BigDecimal(String)

BigDecimaldoubleBigDecimal的输入一起使用时,输入为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 ,不应该是一样的吗?

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

你是绝对正确的,这正是因为double的不精确。

但由于这是一个BigDecimal ,不应该是一样的吗?

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

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

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

标准支持这一点,除非另有说明,否则浮点文字默认为double

Java文档有它的答案。 根据BigDecimal的 Java文档(double val)

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

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