new BigDecimal(double) 与 new BigDecimal(String) [重复]

new BigDecimal(double) vs new BigDecimal(String) [duplicate]

提问人:dardeshna 提问时间:4/15/2015 最后编辑:dardeshna 更新时间:4/15/2015 访问量:7407

问:

这个问题在这里已经有答案了:
将 double 转换为 BigDecimal 并设置 BigDecimal 精度 (9 个答案)
8年前关闭。

当与输入和输入一起使用时,似乎会出现不同的结果。BigDecimaldoubleBigDecimalString

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

java bigdecimal 双精度

评论

0赞 pL4Gu33 4/15/2015
看看 a,b 和 c,d ...这已经是不同的;)看看 stackoverflow.com/questions/12395281/...
1赞 fge 4/15/2015
这是因为精度有限;这就是适合您的 IEEE 754。double
1赞 SnakeDoc 4/15/2015
您可以使用以下方法更正它.setScale(10, BigDecimal.ROUND_HALF_UP);

答:

6赞 Patrick Collins 4/15/2015 #1

是的,这是浮点误差。问题在于,在作为参数传递给 --- 之前,文字 和 被表示为双精度,值得注意的是,的构造函数将 a 作为参数。0.3333333330.666666666BigDecimalBigDecimaldouble

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

评论

0赞 Solomon Slow 4/15/2015
这不是浮点错误。浮点代码的行为方式完全符合其预期行为方式。唯一的问题是程序员对它的行为方式的期望。“问题”是它不表示由 表示的相同有理数。但是,这不是一个错误,除非通过更改 Java 语言规范,使其不再被解释为 IEEE 二进制双精度,否则无法“修复”。0.333333333new BigDecimal("0.333333333")0.333333333
0赞 Patrick Collins 4/15/2015
@jameslarge我知道IEEE二进制双精度是如何工作的,---使用它们导致的不精确性通常被称为“错误”。例如,请参阅 wikipediaOracle 文档。这是统计误差意义上的误差,而不是 .FileNotFoundError
0赞 Solomon Slow 4/15/2015
哦。。。右。。。那种错误。我想我最近有点全神贯注于软件缺陷(请不要问我为什么),我开始看到它们,即使它们没有。
13赞 Sergey Kalinichenko 4/15/2015 #2

我说这是因为双重不精确性错了吗?

你说得很对,这恰恰是因为不精确。double

但既然是,就不应该是一样的吗?BigDecimal

不,它不应该。该错误是在您创建的那一刻引入的,因为 constant 中已经嵌入了一个错误。在这一点上,你无法做任何事情来修复这个表示错误:众所周知的马到那时已经离开了谷仓,所以关门为时已晚。new BigDecimal(0.333333333)0.333333333

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

0赞 Sebastian Brudzinski 4/15/2015 #3

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

5赞 Masudul 4/15/2015 #4

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

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