Reputation: 85
import java.math.BigDecimal;
public class TestNumber {
public static void main(String[] args) {
BigDecimal bd = new BigDecimal(0);
bd = bd.add(new BigDecimal(19.89));
System.out.println(bd.doubleValue() + " - \t " + bd);
}
}
I have multiple BidDecimals fields and arithmetic operations/comparations, the problem is with arithmetic results and decimals values.
For the above example the output is as follows:
19.89 - 19.8900000000000005684341886080801486968994140625
I expects:
19.89
The unexpected result creates other undesirable outputs to perform operations on the field type BigDecimal
Upvotes: 1
Views: 311
Reputation: 96385
The double value displayed by println is not the same as the actual value stored in that double variable.
In any range there are an infinite number of real numbers but only a finite number of representable floating point values. When you define a floating point value, that value may not map to a representable floating point value, in which case you get the representable value that is closest to what you want. (Also keep in mind the representation is in binary, and a lot of numbers that are familiar to us become repeating decimals in binary that have to get truncated.) Here of course it's off by only 0.0000000000000005684341886080801486968994140625.
The lines
double d = 19.89d;
System.out.println(d);
will show you a cleaned-up approximation of what's in d. Java is hiding the messy trailing decimals from you.
On the other hand, these lines
double d = 19.89d
BigDecimal b = new BigDecimal(d);
System.out.println(b);
result in the BigDecimal getting initialized with the entire contents of d, which the BigDecimal reproduces faithfully out to the last trailing digit.
When println is passed the BigDecimal, the BigDecimal's toString method returns a string showing the digits it stored, and println writes that string to the console.
Using
BigDecimal b = new BigDecimal("19.89");
will result in the actual decimal value 19.89 getting stored in the BigDecimal, because no floating point evaluation is involved.
Upvotes: 1
Reputation: 31689
If you have a double
and you need to make a BigDecimal
out of it, without adding all the extra precision, try something like
double d = 19.89; // or something else
bd = new BigDecimal(d, new MathContext(15));
This tells it to keep only 15 digits of precision (which is about how many digits of precision a double
supports). This creates a BigDecimal
whose toString()
returns
"19.8900000000000"
which isn't quite perfect, since all the trailing zeroes will show up, but it doesn't give you the extra non-zero digits you're getting.
Upvotes: 0
Reputation: 159754
The precision is already lost once you use the BigDecimal
constructor that accepts double
values. The value youre seeing is the true IEEE 754 representation of the number. You can use
bd = bd.add(new BigDecimal("19.89"));
Upvotes: 3