aspose file tools*
The moose likes Beginning Java and the fly likes BigDecimal Rounding Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "BigDecimal Rounding" Watch "BigDecimal Rounding" New topic
Author

BigDecimal Rounding

Michael Remijan
Author
Ranch Hand

Joined: May 29, 2002
Posts: 126
    
    5

Hi,
I'm getting a different value than expected using BigDecimal.setScale() method and I wanted to see if someone can tell me why.
Basically, (and this is not currency) a number rounded to 2 digits right of the decimal point. I also choose ROUND_HALF_DOWN so that <=5 is rounded down and >=5 is rounded up.
While JUniting, I set a test case that
0.195 should be equal to 0.19. I expected this to be correct because ROUND_HALF_DOWN is for <=5 and since 5=5 it should round down. But it's not. I'm getting 2.0.
Is this right or do I understand this wrong?
Thanks,
Mike


Java EE Evangelist — Author, EJB 3 in Action 2nd Edition — Java Community Process Member
Joel McNary
Bartender

Joined: Aug 20, 2001
Posts: 1824


I'm getting 2.0.

I assume you mean 0.20?
Here's what (is probably) going on, and this may be the case on your system as well (I am running JRE 1.4.1_02 on a Windows XP (sp1) box with a 2.4 Ghz Pentium 4 processor, in case it matters...)

Result?
aDecimal: 0.195000000000000006661338147750939242541790008544921875
another: 0.20
ROUND_HALF_DOWN states that it will "round towards 'nearest neighbor' unless both neighbors are equidistant, in which case round down."
However, we are not equidistant here! 0.20 is 000000000000000006661338147750939242541790008544921875 closer than .19 is, so it chooses 0.20
I've never come across a satisfactory solution to this problem, and in fact have my own methods for rounding as a work-around (they convert the BigDecimal to a string and round from there!) Anybody else have expierence with this/have a solution?


Piscis Babelis est parvus, flavus, et hiridicus, et est probabiliter insolitissima raritas in toto mundo.
Michael Remijan
Author
Ranch Hand

Joined: May 29, 2002
Posts: 126
    
    5

yes, i'm sorry I did mean 0.20. I tried IBM's implementation of BigDecimal and I get the same thing. So as not to re-invent the wheel, would you be willing to share your parsing code?
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Consult the API for BigDecimal. The comments for the BigDecimal(double) constructor explain your problem, and point to a solution: use BigDecimal(String) instead for an exact representation of a fractional value.
BigDecimal aDecimal = new BigDecimal("0.1950");
This gives the results you'd expect.


"I'm not back." - Bill Harding, Twister
Michael Remijan
Author
Ranch Hand

Joined: May 29, 2002
Posts: 126
    
    5

Thanks Jim, I'll give that a try. BTW, I did consult that BigDecimal API, very heavily in fact. But after test coding for a 4-5 hours, it was just time to ask.
Thanks for you help everyone.
Michael Remijan
Author
Ranch Hand

Joined: May 29, 2002
Posts: 126
    
    5

That did it. All my JUnit tests worked.
Spencer J Lee
Ranch Hand

Joined: Mar 19, 2003
Posts: 30
I have a similar problem, but the String solution doesn't quite solve it completely... Just wondering if anyone had any suggestions.
To summarize what I'm doing, the double I'm trying to round is the solution to some algebraic equation.
Here is an example of my current rounding...

Where someAlgEqution() is some algebraic equation that returns a double.
I have problems when someAlgEquation returns a double like 2.14634999999998. Since the 5th decimal is a 4, 2.1463. But really, its only a 4 because 2.14635 isn't represented exactly...
Any suggestions?
Thanks,
Spencer
Michael Remijan
Author
Ranch Hand

Joined: May 29, 2002
Posts: 126
    
    5

I'm not sure about this one. Perhaps this is one case where you would want to use a double instead of a string. Or use a double first to do an initial rounding and then a string to finish it off?
Joe Schinny
Greenhorn

Joined: Nov 06, 2009
Posts: 1
Scaling twice should work. Scale to an extra precision point, then scale the result.

 
 
subject: BigDecimal Rounding