双精度浮点数转换成 BigDecimal 时出现错误值?

5

我正在尝试从字符串中创建一个BigDecimal对象。不要问我为什么,我只是需要它!这是我的代码:

Double theDouble = new Double(".3");
System.out.println("The Double: " + theDouble.toString());
BigDecimal theBigDecimal = new BigDecimal(theDouble);
System.out.println("The Big: " + theBigDecimal.toString());

这是我获得的输出?
The Double: 0.3
The Big: 0.299999999999999988897769753748434595763683319091796875

有什么想法吗?
4个回答

12

创建一个double类型时,数值0.3无法被准确表示。你可以通过从字符串中直接创建BigDecimal对象避免使用中间的double类型,例如:

new BigDecimal("0.3")

浮点数表示为二进制小数和指数。因此,有一些数字无法精确表示。在十进制中也存在类似的问题,例如1/3,它是0.333333333.....任何1/3的小数表示都不是精确的。在二进制中,另一组分数也会出现这种情况,0.3就是其中一个在二进制中不精确的数。


为什么它不能精确地表示为双精度浮点数? - Diego
2
@Diego:这是 Stack Overflow 上最常见的问题之一,如果不是最常见的话,至少也在前五名。虽然需要一点时间来理解,但请阅读《计算机科学家应该了解的浮点运算知识》(http://docs.sun.com/source/806-3568/ncg_goldberg.html)。 - Michael Petrotta
你提供了这个问题的规范答案,它是重复问题的应该使用的来关闭最近的类似问题 - Hovercraft Full Of Eels
@HovercraftFullOfEels 我已经忘记我写过哪些“规范”的答案了。这都快7年前的事情了 :-) - Jim Garrison
它经受住了时间的考验。 - Hovercraft Full Of Eels

1

由于new Double(".3")无法准确表示,最接近的值是0x1.3333333333333P-2.299999999999999988897769753748434595763683319091796875,所需的是:

Double theDouble = new Double(".3");
System.out.println("The Double: " + theDouble.toString());
BigDecimal theBigDecimal = new 
BigDecimal(theDouble).setScale(2, RoundingMode.CEILING);  // <-- here
System.out.println("The Big: " + theBigDecimal.toString());

这将打印输出:

The Double: 0.3
The Big: 0.30

1
另一种方法是使用MathContext.DECIMAL32,它保证了7位数字的精度(在我们的情况下足够好):
Double theDouble = new Double(".3");
System.out.println("The Double: " + theDouble.toString());
BigDecimal theBigDecimal = new BigDecimal(theDouble, MathContext.DECIMAL32);  // <-- here
System.out.println("The Big: " + theBigDecimal.toString());

输出

The Double: 0.3
The Big: 0.3000000

0
你可以给一个大的十进制数指定精度。例如,在你的例子中添加:
Double theDouble = new Double(".3");
theBigDecimal = new BigDecimal(theDouble, new MathContext(2));
System.out.println("The Big: " + theBigDecimal.toString());

这将打印出“0.30”


谢谢,但我并不总是知道精度会是多少。实际上,我正在从文件中读取字符串。 - Diego

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接