Win a copy of The Java Performance Companion this week in the Performance forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

BigDecimal ROUND_HALF_EVEN rounding mode and the number of digits to the right of the decimal point

 
albert kao
Ranch Hand
Posts: 252
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
My financial application requirement is ROUND_HALF_EVEN rounding mode and the number of digits to the right of the decimal point is 2 in the BigDecimal class.
How to achieve that consistently across multiple java files (Screen1.java, Screen2.java, ...) and reduce the redundant setup code?
Should I use MathContext class?

Test program.
Screen1.java:
[code=java]
BigDecimal number = new BigDecimal("1.01234");
result = number.round(new MathContext(2, RoundingMode.ROUND_HALF_EVEN));
System.out.println("result " + result);

result = number.setScale(2, RoundingMode.ROUND_HALF_EVEN);
System.out.println("result " + result);
 
Campbell Ritchie
Sheriff
Pie
Posts: 49396
62
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What output are you getting? Have look at this old post. When you go through the API Documentation, look for scale and precision. They mean different things. Also find out what unscaled value means.
What about a utility class to do the rounding?You should also consider whether to validate the input from the screens before it becomes a BigDecimal.
You should read about the round and setScale methods carefully before using them.
 
albert kao
Ranch Hand
Posts: 252
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:What output are you getting? Have look at this old post. When you go through the API Documentation, look for scale and precision. They mean different things. Also find out what unscaled value means.
What about a utility class to do the rounding?You should also consider whether to validate the input from the screens before it becomes a BigDecimal.
You should read about the round and setScale methods carefully before using them.


My business requirement is that scale is always 2.
Please review the following code.
Thanks.
 
dennis deems
Ranch Hand
Posts: 808
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
albert kao wrote:
My business requirement is that scale is always 2.
Please review the following code.
Thanks.


This looks good to me, although BigDecimal is immutable so setting the scale on the parameters doesn't do anything without an assignment. I assume you want v1 = v1.setScale(SCALE) but this violates the principle that parameters passed into a method shouldn't be modified; setting scale without also setting a rounding mode is dangerous because if there is excess value an ArithmeticException is thrown; and technically, even if you know absolutely that there won't be excess value, setting the scale on the operands is unnecessary since you're going to divide anyway. Also, I would prefer to see less ambiguous names given to the parameters, such as "dividend" and "divisor", but that's just me.

Finally, if the scale is always 2 throughout the application, then I would make this value a constant somewhere, and refer to that constant instead of a method local variable.
 
albert kao
Ranch Hand
Posts: 252
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dennis Deems wrote:
albert kao wrote:
My business requirement is that scale is always 2.
Please review the following code.
Thanks.


This looks good to me, although BigDecimal is immutable so setting the scale on the parameters doesn't do anything without an assignment. I assume you want v1 = v1.setScale(SCALE) but this violates the principle that parameters passed into a method shouldn't be modified; setting scale without also setting a rounding mode is dangerous because if there is excess value an ArithmeticException is thrown; and technically, even if you know absolutely that there won't be excess value, setting the scale is unnecessary since you're going to divide anyway. Also, I would prefer to see less ambiguous names given to the parameters, such as "dividend" and "divisor", but that's just me.

Finally, if the scale is always 2 throughout the application, then I would make this value a constant somewhere, and refer to that constant instead of a method local variable.

As per your suggestions, the code is revised as follows:


I should add similar methods for multiply, add, subtract & compareTo, shouldn't I?
 
Paul Clapham
Sheriff
Posts: 21126
32
Eclipse IDE Firefox Browser MySQL Database
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
But apart from what Dennis already said, your posted code returns a result which isn't rounded to two decimal places. That wasn't your requirement, was it? (Your requirement isn't all that clear: for example does it apply to intermediate results in complex calculations, or only to the end result?)

Anyway have a look at this code fragment and see what it does:



Note that in line 1, for example, just using "setScale(2)" throws an exception; you have to specify a rounding mode along with the number of decimal places. Note also that the "7" in line 3 is the number of digits and not the number of decimal places. But look especially at the last value output.

 
albert kao
Ranch Hand
Posts: 252
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Paul Clapham wrote:But apart from what Dennis already said, your posted code returns a result which isn't rounded to two decimal places. That wasn't your requirement, was it? (Your requirement isn't all that clear: for example does it apply to intermediate results in complex calculations, or only to the end result?)

Anyway have a look at this code fragment and see what it does:



Note that in line 1, for example, just using "setScale(2)" throws an exception; you have to specify a rounding mode along with the number of decimal places. Note also that the "7" in line 3 is the number of digits and not the number of decimal places. But look especially at the last value output.


Please review:




I should add similar methods for multiply, add, subtract & compareTo, shouldn't I?
 
Winston Gutkowski
Bartender
Pie
Posts: 10422
63
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
albert kao wrote:My business requirement is that scale is always 2.

Then I would suggest that precision is irrelevant, and I'd probably do something like:or (maybe even better) simply provide a setToRequiredScale(BigDecimal) method and do something like
BigDecimal result = setToRequiredScale(v1.divide(v2));
That way you can apply it to any calculation or value.

Winston

PS: Another oft-forgotten fact is that BigDecimal is not final, so you could actually extend it to provide a setToRequiredScale() method (or, indeed, apply it to every returned result).
 
albert kao
Ranch Hand
Posts: 252
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:
albert kao wrote:My business requirement is that scale is always 2.

Then I would suggest that precision is irrelevant, ....

Scale and precision is independent, so I do not think that precision is irrelevant.
 
Winston Gutkowski
Bartender
Pie
Posts: 10422
63
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
albert kao wrote:
Winston Gutkowski wrote:
albert kao wrote:My business requirement is that scale is always 2.

Then I would suggest that precision is irrelevant, ....

Scale and precision is independent, so I do not think that precision is irrelevant.

But your statement doesn't include any reference to precision, therefore we can't make any assumptions about it; which to me makes it irrelevant for the purposes of this discussion.

Winston
 
albert kao
Ranch Hand
Posts: 252
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:
albert kao wrote:
Winston Gutkowski wrote:
albert kao wrote:My business requirement is that scale is always 2.

Then I would suggest that precision is irrelevant, ....

Scale and precision is independent, so I do not think that precision is irrelevant.

But your statement doesn't include any reference to precision, therefore we can't make any assumptions about it; which to me makes it irrelevant for the purposes of this discussion.

Winston


You are right.
My requirement should also include:
The precision is either 15 or 8.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic