Solved

BigDecimal division rounding

Posted on 2010-11-10
6
698 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
Comment Utility
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
Comment Utility
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
Comment Utility
It shouldn't be a part of the api.
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 86

Expert Comment

by:CEHJ
Comment Utility
Did you try it using string ctors?
0
 

Author Comment

by:aDane1234
Comment Utility
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
Comment Utility
That's ok
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

An old method to applying the Singleton pattern in your Java code is to check if a static instance, defined in the same class that needs to be instantiated once and only once, is null and then create a new instance; otherwise, the pre-existing insta…
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…
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…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.

728 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

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now