Those are two separate questions: "What should I use for BigDecimal?" and "What do I do in general?"
For BigDecimal: this is a bit tricky, because they don't do the same thing. BigDecimal.valueOf(double) will use the canonical String representation of the double value passed in to instantiate the BigDecimal object. In other words: The value of the BigDecimal object will be what you see when you do System.out.println(d).
If you use new BigDecimal(d) however, then the BigDecimal will try to represent the double value as accurately as possible. This will usually result in a lot more digits being stored than you want. Strictly speaking, it's more correct than valueOf(), but it's a lot less intuitive.
There's a nice explanation of this in the JavaDoc:
The results of this constructor can be somewhat unpredictable. One might assume that writing
new BigDecimal(0.1)in Java creates aBigDecimalwhich is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as adouble(or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding.
In general, if the result is the same (i.e. not in the case of BigDecimal, but in most other cases), then valueOf() should be preferred: it can do caching of common values (as seen on Integer.valueOf()) and it can even change the caching behaviour without the caller having to be changed. new will always instantiate a new value, even if not necessary (best example: new Boolean(true) vs. Boolean.valueOf(true)).
Those are two separate questions: "What should I use for BigDecimal?" and "What do I do in general?"
For BigDecimal: this is a bit tricky, because they don't do the same thing. BigDecimal.valueOf(double) will use the canonical String representation of the double value passed in to instantiate the BigDecimal object. In other words: The value of the BigDecimal object will be what you see when you do System.out.println(d).
If you use new BigDecimal(d) however, then the BigDecimal will try to represent the double value as accurately as possible. This will usually result in a lot more digits being stored than you want. Strictly speaking, it's more correct than valueOf(), but it's a lot less intuitive.
There's a nice explanation of this in the JavaDoc:
The results of this constructor can be somewhat unpredictable. One might assume that writing
new BigDecimal(0.1)in Java creates aBigDecimalwhich is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as adouble(or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding.
In general, if the result is the same (i.e. not in the case of BigDecimal, but in most other cases), then valueOf() should be preferred: it can do caching of common values (as seen on Integer.valueOf()) and it can even change the caching behaviour without the caller having to be changed. new will always instantiate a new value, even if not necessary (best example: new Boolean(true) vs. Boolean.valueOf(true)).
If you are using your BigDecimal objects to store currency values, then I strongly recommend that you do NOT involve any double values anywhere in their calculations.
As stated in another answer, there are known accuracy issues with double values and these will come back to haunt you big time.
Once you get past that, the answer to your question is simple. Always use the constructor method with the String value as the argument to the constructor, as there is no valueOf method for String.
If you want proof, try the following:
Use with AIBigDecimal bd1 = new BigDecimal(0.01);
BigDecimal bd2 = new BigDecimal("0.01");
System.out.println("bd1 = " + bd1);
System.out.println("bd2 = " + bd2);
You'll get the following output:
Use with AIbd1 = 0.01000000000000000020816681711721685132943093776702880859375
bd2 = 0.01
See also this related question
I would use Arrays.fill() as that will would for any number of zeros (or any other BigDecimal value you like) This works because BigDecimal is immutable, don't do this for mutable values ;)
BigDecimal[] val = new BigDecimal[N];
Arrays.fill(val, BigDecimal.ZERO);
You can use the predefined BigDecimal.ZERO constant:
BigDecimal[] val = { BigDecimal.ZERO,
BigDecimal.ZERO,
BigDecimal.ZERO };
First off, BigDecimal is immutable. You must return the result from your setScale method call:
spread = spread.setScale(2, RoundingMode.HALF_EVEN);
Next you must improve your accuracy of the second BigDecimal since it is being derived from a double -- not a very accurate entity. So try a String:
spread.compareTo(new BigDecimal("0.02"))
0.02 gets evaluated to
java.math.BigDecimal = 0.0200000000000000004163336342344337026588618755340576171875
You have to setScale(2, RoundingMode.HALF_EVEN) there too.
The reason of such behaviour is that the string that is printed is the exact value - probably not what you expected, but that's the real value stored in memory - it's just a limitation of floating point representation.
According to javadoc, BigDecimal(double val) constructor behaviour can be unexpected if you don't take into consideration this limitation:
The results of this constructor can be somewhat unpredictable. One might assume that writing new BigDecimal(0.1) in Java creates a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding.
So in your case, instead of using
double val = 77.48;
new BigDecimal(val);
use
BigDecimal.valueOf(val);
Value that is returned by BigDecimal.valueOf is equal to that resulting from invocation of Double.toString(double).
It prints 47.48000 if you use another MathContext:
BigDecimal b = new BigDecimal(d, MathContext.DECIMAL64);
Just pick the context you need.