为什么没有Java"新的BigDecimal(双)"被弃用?

时间:2017-04-11 15:58:37

标签: java double bigdecimal

来自BigDecimal's constructor

  

这个构造函数的结果可能有些不可预测。一   可能会假设在Java中编写新的BigDecimal(0.1)会创建一个   BigDecimal正好等于0.1(未缩放的值为1,带有   比例为1),但它实际上等于   0.1000000000000000055511151231257827021181583404541015625。这是因为0.1不能完全表示为double(或者为此)   重要的是,作为任何有限长度的二进制分数)。因此,价值   传入构造函数的不完全等于   0.1,尽管有外表。

     

另一方面,String构造函数是完全可预测的:   编写新的BigDecimal(" 0.1")会创建一个完全正确的BigDecimal   等于0.1,正如人们所期望的那样。因此,一般来说   建议首先使用String构造函数   之一。

     

当必须将double用作BigDecimal的源时,请注意   这个构造函数提供了精确的转换;它没有给出   使用。将double转换为String的结果相同   Double.toString(double)方法然后使用BigDecimal(String)   构造函数。要获得该结果,请使用静态valueOf(double)   方法

那么为什么他们只是弃用它并将功能更改为valueOf(double)?什么是不可预测的价值创造了什么?

2 个答案:

答案 0 :(得分:5)

这是完全可以预测的。您可以准确地获得构造函数参数中提供的值。对于双字面0.1“,正如您所引用的那样,传递给构造函数的值并不完全等于0.1”。构造函数忠实地获取传入的值。可以预测。

答案 1 :(得分:3)

该程序说明了new BigDecimal(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));
  }
}