为什么Java的“新的BigDecimal(double)”没有被弃用?

为什么Java的“新的BigDecimal(double)”没有被弃用?,java,double,bigdecimal,Java,Double,Bigdecimal,从 此构造函数的结果可能有些不可预测。一 可能假设在Java中编写新的BigDecimal0.1会创建一个 BigDecimal正好等于0.1,未标度值为1,带 刻度为1,但实际上等于 0.1000000000000000055511151231257827021181583404541015625. 这是因为0.1不能准确地表示为双精度或 物质,作为任何有限长度的二元分数。因此,价值 传递给构造函数的不完全等于 0.1,尽管有外观 另一方面,字符串构造函数是完全可预测的: 编写新的BigDec

此构造函数的结果可能有些不可预测。一 可能假设在Java中编写新的BigDecimal0.1会创建一个 BigDecimal正好等于0.1,未标度值为1,带 刻度为1,但实际上等于 0.1000000000000000055511151231257827021181583404541015625. 这是因为0.1不能准确地表示为双精度或 物质,作为任何有限长度的二元分数。因此,价值 传递给构造函数的不完全等于 0.1,尽管有外观

另一方面,字符串构造函数是完全可预测的: 编写新的BigDecimal0.1将创建一个BigDecimal,它与 等于0.1,正如人们所料。因此,一般来说 建议优先使用字符串构造函数 一个

当必须将double用作BigDecimal的源时,请注意 此构造函数提供精确的转换;它没有给出正确的答案 与使用 Double.toStringdouble方法,然后使用BigDecimalString 构造器。要获得该结果,请使用静态值double 方法


那么,他们为什么不干脆反对它,把它的功能改成valueOfdouble呢?创造出的不可预测的价值有什么意义?

完全可以预测。您可以准确地返回构造函数参数中提供的值。对于双字面值0.1,传递给构造函数的值并不完全等于0.1,如您所引用的。构造函数忠实地拾取传入的值。可以预见。

此程序演示了新的BigDecimaldouble构造函数的实际使用。目标是显示精确结果的范围,该范围将四舍五入到给定的双精度。这取决于能否获得精确值为双精度的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));
  }
}

“不可预测”一词是针对无能的程序员的,不是指实际代码的属性。这个不可预测的语句后面的句子非常清楚地说明了这一点。不赞成的问题已经解决了,但是不改变构造函数以使用valueOfdouble的功能的原因是Java从未改变已发布API的约定。这是一件好事,程序应该期望它们所依赖的行为在将来的版本中将是相同的行为。BigDecimal将数字保留为字符串。如果你有一个银行账户,你想提取与你支付的金额完全相同的金额。任何其他形式的记录数字都会强制执行从十进制到二进制的转换,这意味着许多数字将具有无限的十进制扩展,因此必须进行舍入。@Joanna:不,BigDecimal将数字保留为BigInteger或单个long,这取决于有效位的数量。大整数将其数字保持为整数数组。不在内部使用字符串。它们仅用于将BigDecimal初始化为精确表示字符串表示形式的值。它们所说的是,从文本表示形式double literal 0.1到double的转换不精确。从double到BigDecimal的转换是精确的。但不知道这一点的人可能会认为,用双精度文本初始化的BigDecimal将恰好包含0.1,事实并非如此,因为生成的双精度文本并不完全包含0.1。它对于研究浮点行为非常非常有用。您是否对文档提出异议或重新解释?