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)
这是因为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)