asked on # BigDecimal division rounding

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!

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("Primit

double result2 = val2/const1;

System.out.println("Primit

// 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("BigDec

BigDecimal bdResult2 = bdVal2.divide(bdConst, BigDecimal.ROUND_HALF_UP);

System.out.println("BigDec

}

}

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!

Java

View this solution by signing up for a free trial.

Members can start a 7-Day free trial and enjoy unlimited access to the platform.

It shouldn't be a part of the api.

Did you try it using string ctors?

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.

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.

That's ok

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? :-)