?
Solved

BigDecimal division rounding

Posted on 2010-11-10
6
Medium Priority
?
745 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
  • 2
6 Comments
 
LVL 92

Accepted Solution

by:
objects earned 2000 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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

Important Lessons on Recovering from Petya

In their most recent webinar, Skyport Systems explores ways to isolate and protect critical databases to keep the core of your company safe from harm.

Question has a verified solution.

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

After being asked a question last year, I went into one of my moods where I did some research and code just for the fun and learning of it all.  Subsequently, from this journey, I put together this article on "Range Searching Using Visual Basic.NET …
Java Flight Recorder and Java Mission Control together create a complete tool chain to continuously collect low level and detailed runtime information enabling after-the-fact incident analysis. Java Flight Recorder is a profiling and event collectio…
Viewers will learn about the different types of variables in Java and how to declare them. Decide the type of variable desired: Put the keyword corresponding to the type of variable in front of the variable name: Use the equal sign to assign a v…
Viewers will learn about basic arrays, how to declare them, and how to use them. Introduction and definition: Declare an array and cover the syntax of declaring them: Initialize every index in the created array: Example/Features of a basic arr…
Suggested Courses

650 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