新的 BigDecimal(双)与新的 BigDecimal(字符串)
new BigDecimal(double) vs new BigDecimal(String)
当 BigDecimal
与输入 double
一起使用时,BigDecimal
与输入 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
,不应该是一样的吗?
是的,这是浮点数错误。问题是文字 0.333333333
和 0.666666666
在作为参数传递给 BigDecimal
之前被表示为双精度数——值得注意的是,BigDecimal
的构造函数采用 double
作为参数。
这是标准所支持的,它表示floating point literals default to double
unless otherwise specified。
Am I wrong in saying that this is because of double imprecision?
你说得很对,这正是因为double
的不精确。
But since this is a BigDecimal
, shouldn't it be the same?
不,不应该。该错误是在您创建 new BigDecimal(0.333333333)
时引入的,因为 0.333333333
常量中已经嵌入了错误。到那时,您将无能为力来修复此表示错误:众所周知那匹马那时已经离开了谷仓,所以关门已经太晚了。
另一方面,当您传递 String
时,十进制表示与字符串完全匹配,因此您会得到不同的结果。
当您以任何方式定义双精度变量时,在大多数情况下,它不会是您定义的值,而是最接近的二进制表示形式。您正在向构造函数传递一个双精度值,因此已经提供了那个小的不精确性。
Java 文档有答案。根据 Java BigDecimal(double val)
的文档
The results of this constructor can be somewhat unpredictable. One
might assume that writing new BigDecimal(0.1) in Java creates a
BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with
a scale of 1), but it is actually equal to
0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double.
当 BigDecimal
与输入 double
一起使用时,BigDecimal
与输入 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
,不应该是一样的吗?
是的,这是浮点数错误。问题是文字 0.333333333
和 0.666666666
在作为参数传递给 BigDecimal
之前被表示为双精度数——值得注意的是,BigDecimal
的构造函数采用 double
作为参数。
这是标准所支持的,它表示floating point literals default to double
unless otherwise specified。
Am I wrong in saying that this is because of double imprecision?
你说得很对,这正是因为double
的不精确。
But since this is a
BigDecimal
, shouldn't it be the same?
不,不应该。该错误是在您创建 new BigDecimal(0.333333333)
时引入的,因为 0.333333333
常量中已经嵌入了错误。到那时,您将无能为力来修复此表示错误:众所周知那匹马那时已经离开了谷仓,所以关门已经太晚了。
另一方面,当您传递 String
时,十进制表示与字符串完全匹配,因此您会得到不同的结果。
当您以任何方式定义双精度变量时,在大多数情况下,它不会是您定义的值,而是最接近的二进制表示形式。您正在向构造函数传递一个双精度值,因此已经提供了那个小的不精确性。
Java 文档有答案。根据 Java BigDecimal(double val)
的文档The results of this constructor can be somewhat unpredictable. One might assume that writing new BigDecimal(0.1) in Java creates a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double.