Java BigDecimal difference

爷,独闯天下 提交于 2021-01-28 00:33:18

问题


I wanted to see if anyone can explain why the following code works with valueOf but not others.

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)));

   }
 }

The output looks like:

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

My question is: What does valueOf() do to get the precision? Is there any other way of getting the correct result without rounding off to the 2 digits manually?

thanks,


回答1:


Looking at the source code for BigDecimal, it does:

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));
}

From its JavaDoc:

Translates a double into a BigDecimal, using the double's canonical string representation provided by the Double.toString(double) method.

Note: This is generally the preferred way to convert a double (or float) into a BigDecimal, as the value returned is equal to that resulting from constructing a BigDecimal from the result of using Double.toString(double).

Because of floating-point representation, a double value is not exactly what you set it as. However, during String representation, it rounds off what it displays. (All of the rules are on it's JavaDoc).

Furthermore, because of this rounding, if you did:

BigDecimal d = BigDecimal.valueOf(4.00000000000000000000000000000000001));

you would get the wrong value. (d == 4.0)

So, it's pretty much always better to initialize these with strings.




回答2:


BigDecimal.valueOf(double) first does a conversion from double to String, then String to BigDecimal.

In the first case, you're starting with a double or float, converting to BigDecimal, calculating the difference. In the second case, you're starting with double or float, converting to a String, then converting to BigDecimal, then calculating the difference.




回答3:


From the Javadocs:

public static BigDecimal valueOf(double val)

Translates a double into a BigDecimal, using the double's canonical string representation provided by the Double.toString(double) method. Note: This is generally the preferred way to convert a double (or float) into a BigDecimal, as the value returned is equal to that resulting from constructing a BigDecimal from the result of using Double.toString(double).

I think this answers both of your questions.

Cheers,




回答4:


The valueOf works because it calls Double.toString. from the Javadoc:

public static BigDecimal valueOf(double val)

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

canonical string representation provided by the Double.toString(double) method.

When you pass a double into the BigDecimal constructor, the constructor takes the floating-point value and reproduces it exactly. The toString code finds an approximation for the floating point value.

In case you didn't notice, using System.out.println() to show a floating point number doesn't show the same results as if you wrap the floating point number in a BigDecimal first (using the BigDecimal constructor that takes a double).



来源:https://stackoverflow.com/questions/6021369/java-bigdecimal-difference

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!