Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BigDecimal Error

In Java, I have defined k as double k=0.0;

I am taking data from database and adding the same using while loop,

while(rst.next()) {
k = k + Double.parseDouble(rst.getString(5));
}

NOTE: In database, I have values as 125.23, 458.45, 665.99 (all two decimals)

When I display k, I get value as

k = 6034.299999999992

Hence I introduced BigDecimal and changed code to below

      BigDecimal bd = new BigDecimal(k);
      bd = bd.setScale(2,BigDecimal.ROUND_UP);

Now I get new total as bd=6034.30 which is correct.

Problem 1

Well the problem is when I am using same at other place, below is what I am getting

 k  = 157.3
 bd = 157.31

It should have shown bd=157.30 as after adding manually I get 157.30.

Any reason why it is showing as 157.31.

Problem 2

Also any reason why k is showing so many decimal values? Below are different values I am getting for double variable k

157.3
67.09
1014.6000000000003
229.06999999999996

I don't understand sometime it displays one decimal, sometime it display 2 decimal and most of the time it show 14 decimal value.

Any suggestion would be appreciated.

like image 230
Fahim Parkar Avatar asked Jan 17 '12 07:01

Fahim Parkar


People also ask

What is a BigDecimal?

A BigDecimal consists of an arbitrary precision integer unscaled value and a 32-bit integer scale. If zero or positive, the scale is the number of digits to the right of the decimal point. If negative, the unscaled value of the number is multiplied by ten to the power of the negation of the scale.

What is BigDecimal used for?

The BigDecimal class provides operations for arithmetic, scale manipulation, rounding, comparison, hashing, and format conversion. The toString() method provides a canonical representation of a BigDecimal . The BigDecimal class gives its user complete control over rounding behavior.

What can I use instead of BigDecimal?

If you need to use division in your arithmetic, you need to use double instead of BigDecimal.

How do I get rid of trailing zeros in BigDecimal?

stripTrailingZeros() is an inbuilt method in Java that returns a BigDecimal which is numerically equal to this one but with any trailing zeros removed from the representation. So basically the function trims off the trailing zero from the BigDecimal value.


2 Answers

You're still going via double. Stick to BigDecimal everywhere:

BigDecimal k = BigDecimal.ZERO;
while (rst.next()) {
    k = k.add(new BigDecimal(rst.getString(5));
}

Alternatively - and preferrably, if the field in the database is actually a decimal value:

BigDecimal k = BigDecimal.ZERO;
while (rst.next()) {
    k = k.add(rst.getBigDecimal(5));
}
like image 199
Jon Skeet Avatar answered Sep 20 '22 03:09

Jon Skeet


As to your second question, double is a binary floating point number. This means that it is expressed as a sum of powers of two. Don't ever use those for calculating monetary values. (if that's what you're summing up there). BigDecimal uses decimal arithmetic, so this is more in line to what we use.

Numbers such as 0.1 are infinite fractions in binary, in this case: 0.000110011... thus you cannot get a reliable and exact result from using double.

like image 25
Joey Avatar answered Sep 20 '22 03:09

Joey