Java BigDecimal的区别

时间:2011-05-16 17:56:56

标签: java double bigdecimal

我想知道是否有人可以解释为什么以下代码适用于valueOf但不适用于其他代码。

import java.math.BigDecimal; 
public class Change {
   public static void main(String args[]) {
     double a = 4.00d;
     double b = 3.10d;
     BigDecimal a1 = new BigDecimal(a);
     BigDecimal b1 = new BigDecimal(b);
     BigDecimal diff = a1.subtract(b1);
     System.out.println("Double difference");
     System.out.println(diff);

     float c = 4.00f;
     float d = 3.10f;
     BigDecimal a2 = new BigDecimal(c);
     BigDecimal b2 = new BigDecimal(d);
     BigDecimal diff2 = a2.subtract(b2);
     System.out.println("Float difference");
     System.out.println(diff2);

     System.out.println("Valueof Difference");
     System.out.println(BigDecimal.valueOf(4.00).subtract(BigDecimal.valueOf(3.10)));

   }
 }

输出如下:

>java Change
 Double difference
  0.899999999999999911182158029987476766109466552734375
 Float difference
  0.900000095367431640625
 Valueof Difference
 0.9

我的问题是:valueOf()做了什么来获得精度? 有没有其他方法可以获得正确的结果而无需手动四舍五入到这两个数字?

感谢,

4 个答案:

答案 0 :(得分:8)

查看BigDecimal的源代码,它确实:

public static BigDecimal valueOf(double val) {
    // Reminder: a zero double returns '0.0', so we cannot fastpath
    // to use the constant ZERO.  This might be important enough to
    // justify a factory approach, a cache, or a few private
    // constants, later.
    return new BigDecimal(Double.toString(val));
}

来自JavaDoc:

  

将double转换为BigDecimal,   使用double的规范字符串   代表提供的   Double.toString(double)方法。

     

注意:这通常是首选方式   将double(或float)转换为   BigDecimal,返回的值是   等于由此产生的   从中构造BigDecimal   使用的结果   Double.toString(双)。

由于浮点表示,double值与您设置的不完全相同。但是,在String表示期间,它会将其显示的内容四舍五入。 (所有规则都在JavaDoc)。

此外,由于这种四舍五入,如果你这样做:

BigDecimal d = BigDecimal.valueOf(4.00000000000000000000000000000000001));

你会得到错误的价值。 (d == 4.0)

因此,用字符串初始化它们总是更好。

答案 1 :(得分:1)

valueOf有效,因为它调用Double.toString。来自Javadoc:

public static BigDecimal valueOf(double val)

    Translates a double into a BigDecimal, using the double's
     

规范字符串表示   由...提供   Double.toString(double)方法。

当您将double传递给BigDecimal构造函数时,构造函数将获取浮点值并完全再现它。 toString代码找到浮点值的近似值。

如果您没有注意到,使用System.out.println()显示浮点数并不会显示与首先在BigDecimal中包装浮点数相同的结果(使用BigDecimal构造函数花了两倍。

答案 2 :(得分:1)

BigDecimal.valueOf(double)首先从double转换为String,然后将String转换为BigDecimal。

在第一种情况下,您将以double或float开头,转换为BigDecimal,计算差异。在第二种情况下,你从double或float开始,转换为String,然后转换为BigDecimal,然后计算差异。

答案 3 :(得分:1)

来自Javadocs

public static BigDecimal valueOf(double val)

  

将double转换为BigDecimal,   使用double的规范字符串   代表提供的   Double.toString(double)方法。注意:   这通常是首选方式   将double(或float)转换为   BigDecimal,返回的值是   等于由此产生的   从中构造BigDecimal   使用的结果   Double.toString(双)。

我认为这可以回答你的两个问题。

干杯,