“new BigDecimal(13.3D)”导致不精确的“13.300000000000000007105..”?

2022-09-02 22:48:39

Java怎么会这么痛苦呢?BigDecimal

Double d = 13.3D;

BigDecimal bd1 = new BigDecimal(d);
BigDecimal bd2 = new BigDecimal(String.valueOf(d));


System.out.println("RESULT 1: "+bd1.toString());
System.out.println("RESULT 2: "+bd2.toString());

RESULT 1: 13.300000000000000710542735760100185871124267578125
RESULT 2: 13.3

是否有任何情况需要结果1?我知道Java 1.5改变了方法,但这是预期的结果吗?toString()

我也意识到有等,但我正在使用的库有用地使用了一个,我无法改变它:-(BigDecimaldoubleValue()toString()

干杯。


答案 1

好吧,API确实解决了构造函数中明显的不一致:BigDecimal(double val)

  1. 此构造函数的结果可能有些不可预测。有人可能会假设在Java中编写新的BigDecimal(0.1)会创建一个正好等于0.1的BigDecimal(一个未缩放的值1,小数位数为1),但它实际上等于0.100000000000000000000055511151231257827021181583404541015625。这是因为 0.1 不能完全表示为双精度值(或者,就此而言,不能表示为任何有限长度的二进制分数)。因此,尽管外观不同,传递给构造函数的值并不完全等于 0.1。

  2. 另一方面,String构造函数是完全可预测的:编写新的BigDecimal(“0.1”)会创建一个正好等于0.1的BigDecimal,正如人们所期望的那样。因此,通常建议优先使用 String 构造函数而不是此构造函数。

  3. 当必须将双精度值用作 BigDecimal 的源时,请注意,此构造函数提供了精确的转换;它不会给出与使用 Double.toString(double) 方法然后使用 BigDecimal(String) 构造函数将 double 转换为 String 相同的结果。若要获取该结果,请使用静态值Of(double) 方法

故事的寓意:痛苦似乎是自己造成的,只需使用新的BigDecimal(String val)BigDecimal.valueOf(double val)代替=)


答案 2

你的问题与 无关,而与 一切都无关,它不能准确地表示 13.3,因为它在内部使用二进制分数。BigDecimalDouble

因此,您的错误将在第一行中引入。第一个只是简单地保留它,同时做一些鱼腥的舍入,导致第二个具有所需的内容,这几乎是通过运气。BigDecimalString.valueOf()


推荐