Solved

BigDecimal division rounding

Posted on 2010-11-10
6
719 Views
Last Modified: 2012-05-10
Hello!

Take a look at this code:

package crap;
import java.math.BigDecimal;
public class BDCalc {
    public static void main(String[] args){
        // Declare primitives
        double const1 = 1.2991;
        double val1 = 0.9;
        double val2 = 0.5;

        // Divide with primitives:
        double result1 = val1/const1;
        System.out.println("Primitives ex. 1: " + result1);
        double result2 = val2/const1;
        System.out.println("Primitives ex. 2: " + result2);

        // Declare BigDecimals with same values
        BigDecimal bdConst = new BigDecimal(const1);
        BigDecimal bdVal1 = new BigDecimal(val1);
        BigDecimal bdVal2 = new BigDecimal(val2);

        // Divide with BigDecimal
        BigDecimal bdResult1 = bdVal1.divide(bdConst, BigDecimal.ROUND_HALF_UP);
        System.out.println("BigDecimal ex.1: " + bdResult1.doubleValue());
        BigDecimal bdResult2 = bdVal2.divide(bdConst, BigDecimal.ROUND_HALF_UP);
        System.out.println("BigDecimal ex.2: " + bdResult2.doubleValue());        
    }
}

At least for me, it produces the following output:

Primitives ex. 1: 0.6927873142945117
Primitives ex. 2: 0.3848818412747287
BigDecimal ex.1: 0.6927873142945117
BigDecimal ex.2: 0.4

Can someone for the life of me explain why the last division - as the only one - is rounded to 0.4 ?!

Best regards to all!
0
Comment
Question by:aDane1234
  • 2
  • 2
  • 2
6 Comments
 
LVL 92

Accepted Solution

by:
objects earned 500 total points
ID: 34106976
you get that because 0.9 probably isn't exactly 0.9 (due to floating point precision) so you end up with a large scale
You should avoid using that constructor for these reasons as its results are unpredictable and instead explicitly specify the scale
0
 

Author Comment

by:aDane1234
ID: 34110975
Thank you very very much for pointing this out!

I must say that this is counter intuitive - when exposing a constructor that accepts a double value, it seems reasonable to expect that the scale is set to the appropriate level - in other words, it seems reasonable to expect that 0.9 is exactly 0.9 :-)

As you correctly put it, the results are unpredictable! The code I presented here was a cut-to-the-bone version of a production-code issue I was presented with yesterday. The system has occasionally performed bad divisions for three months now!

Luckily for me, I did not write that code, but by exposing that constructor, I would say that Sun makes this kind of math-code unneccesarily error-prone. Don't you think it would be better to remove the constructor from the API?

Or is it just me lacking common knowledge? :-)
0
 
LVL 92

Expert Comment

by:objects
ID: 34111070
It shouldn't be a part of the api.
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 86

Expert Comment

by:CEHJ
ID: 34111083
Did you try it using string ctors?
0
 

Author Comment

by:aDane1234
ID: 34111177
CEHJ: Thanks for commenting.

I tried using String constructors now, and it gave this output:

Primitives ex. 1: 0.6927873142945117
Primitives ex. 2: 0.3848818412747287
BigDecimal ex.1: 0.7
BigDecimal ex.2: 0.4

As I see it, this works! Both BigDecimals are now rendered as the exact values they are, and both divisions give output with one decimal.

Thanks a lot for this input - I'm sorry, but I already awarded all the points to objects.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 34111194
That's ok
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
object oriented programming comparison 5 77
how to see all occupied ports on windows 10 laptop 15 77
iterator/ListIterator approach 17 39
Android development question 2 54
INTRODUCTION Working with files is a moderately common task in Java.  For most projects hard coding the file names, using parameters in configuration files, or using command-line arguments is sufficient.   However, when your application has vi…
By the end of 1980s, object oriented programming using languages like C++, Simula69 and ObjectPascal gained momentum. It looked like programmers finally found the perfect language. C++ successfully combined the object oriented principles of Simula w…
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:

829 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question