[英]why java.math.BigDecimal.valueOf(double) does use new BigDecimal(String), instead of new BigDecimal(double)
[英]Why hasn't Java's “new BigDecimal(double)” been deprecated?
此构造函数的结果可能无法预测。 可以假设用Java编写新的BigDecimal(0.1)会创建一个BigDecimal,它精确地等于0.1(未缩放的值1,小数位为1),但实际上等于0.1000000000000000055511511231257827021181583404541015625。 这是因为0.1无法精确表示为双精度(或就此而言,表示为任何有限长度的二进制分数)。 因此,尽管出现,但是传递给构造函数的值并不完全等于0.1。
另一方面,String构造函数是完全可预测的:就像期望的那样,编写新的BigDecimal(“ 0.1”)会创建一个完全等于0.1的BigDecimal。 因此,通常建议优先使用String构造函数。
当必须将double用作BigDecimal的源时,请注意,此构造函数提供了精确的转换。 它与使用Double.toString(double)方法然后使用BigDecimal(String)构造函数将double转换为String的结果不同。 要获得该结果,请使用静态valueOf(double)方法。
那么,为什么他们不只是弃用它,而将功能更改为valueOf(double)呢? 产生不可预测的价值的意义何在?
这是完全可以预见的。 您将准确获得构造函数参数中提供的值。 正如您所引用的,对于双字面量0.1
“,传递给构造函数的值不完全等于0.1
”。 构造函数如实地选择传入的值。
该程序说明了new BigDecimal(double)
构造函数的实际用法。 目的是显示精确结果的范围,该范围将舍入到给定的两倍。 这取决于能否获得具有double精确值的BigDecimal。
import java.math.BigDecimal;
public class Test {
public static void main(String[] args) {
System.out.println(range(1.0));
System.out.println(range(Math.nextUp(1.0)));
System.out.println(range(Math.PI));
}
private static String range(double d){
BigDecimal down = new BigDecimal(Math.nextDown(d));
BigDecimal up = new BigDecimal(Math.nextUp(d));
BigDecimal bd = new BigDecimal(d);
BigDecimal halfUp = midPoint(bd, up);
BigDecimal halfDown = midPoint(down, bd);
Boolean isEven = (Double.doubleToLongBits(d) & 1) == 0;
if(isEven){
return "[" + halfDown + "," + halfUp + "]";
} else {
return "(" + halfDown + "," + halfUp + ")";
}
}
private static BigDecimal midPoint(BigDecimal low, BigDecimal high){
return low.add(high).divide(BigDecimal.valueOf(2));
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.