为什么我们需要将double转换为字符串,然后才能将其转换为BigDecimal?

Pac*_*ier 5 java math

apache commons中的round的源代码如下:

public static double round(double x, int scale, int roundingMethod) {
    try {
        return (new java.math.BigDecimal(Double.toString(x)).setScale(scale, roundingMethod)).doubleValue();
    } catch (NumberFormatException ex) {
        if (Double.isInfinite(x)) {
            return x;
        } else {
            return Double.NaN;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我想知道,在创建BigDecimal原因时,他们选择将双精度转换为字符串(使用Double.toString)而不是简单地使用双精度本身?

换句话说,这有什么问题?:

public static double round(double x, int scale, int roundingMethod) {
    try {
        return (new java.math.BigDecimal(x).setScale(scale, roundingMethod)).doubleValue();
    } catch (NumberFormatException ex) {
        if (Double.isInfinite(x)) {
            return x;
        } else {
            return Double.NaN;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Fab*_*ney 7

这是因为BigDecimal(double)构造函数的结果是不可预测的,如javadoc中所述.

有人可能会假设在Java中编写新的BigDecimal(0.1)会创建一个BigDecimal,它恰好等于0.1(未缩放的值为1,比例为1),但它实际上等于0.1000000000000000055511151231257827021181583404541015625

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

测试用例:

System.out.println(java.math.BigDecimal.valueOf(0.1).toString());
System.out.println(new java.math.BigDecimal(0.1).toString());
Run Code Online (Sandbox Code Playgroud)