• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

BigDecimal math operations problem (Groovy)

 
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello,

I am trying to do various math operations using BigDecimal and are experiencing weird results. Here are some examples. Here's the groovy code.



I am getting the following results. Shouldn't c in the last run be 194.0. Before I used MathContext, I was getting something like 193.98797566565.

a = 550.0
b = 5.5
c = 550.0

a = 194.0
b = 1.94
c = 193.9

THANKS!!!
[ December 02, 2008: Message edited by: Martijn Verburg ]
 
Ranch Hand
Posts: 457
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This is obviously not actual java code. If you Post Real Code we can better help you.
 
Anthony Bailey
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I don't understand....this is real code in Groovy. I may have posted in the wrong place perhaps?
 
Master Rancher
Posts: 4806
72
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This would probably be better in the Groovy forum. Perhaps some nice bartender will move it for you.

Still, the underlying issue is fairly straightforward Java. The problem (if you consider it a problem) is that you've specified a MathContext with 4 digits of precision and RoundingMode.DOWN. This means that when you round 193.98797566565 to four digits you get 193.9 - even though the next digit is 8, you've sait to round down, so that's what happens. If you want "normal" rounding as it's taught in most science and engineering classes, use RoundingMode.HALF_UP.
 
Anthony Bailey
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I was curious how I ended up with 193.98565656 in the first place when multiplying by 100.
 
pie sneak
Posts: 4727
Mac VI Editor Ruby
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Here's a good learning point. Be aware that Groovy additionally makes some object changes to what you're probably assuming are primitive doubles.

There's a consequence that isn't blatantly obvious in the two snippets below:
... new BigDecimal(a, mathContext) ...
... new BigDecimal(b, mathContext) ...

There is no constructor for BigDecimal that takes a (BigDecimal, MathContext)!!! Why isn't this throwing an exception? Groovy is automatically changing types under the covers for... um... convenience. Let's look at example to see what kinds of things Groovy does under the covers.


Consider the following code:
MathContext mathContext = new MathContext(5, RoundingMode.DOWN)
println 5.6789
println new BigDecimal(5.6789)
println new BigDecimal(5.6789, mathContext)

In the first print line, Groovy automatically treats 5.6789 as a BigDecimal under the covers. You can confirm this with println ((5.6789).class) which will print out that the type is BigDecimal.

In the second print line, we now know that the 5.6789 is already a BigDecimal. However, there is no constructor for BigDecimal that accepts another BigDecimal... so Groovy forces our value into a double to satisfy the constructor. This sends the precision into absolute craziness and we get 5.67889999999999961488583721802569925785064697265625 in the console.

The third print line is where things get dangerous because the MathContext is going to hide the precision craziness we saw from line 2. It prints 5.6788 - which is .0001 off from what we expected.

So what could be done differently in your code?

Notice that I went straight for a.divide and b.divide.

Also, I'm using a little trick to make Groovy treat my 100 values as BigDecimals. If I hadn't done this, Groovy would have treated them as BigInteger. I code have alternatively made them 100.0 (with the decimal) and Groovy would have treated them as BigDecimal automatically.

Tricky, huh?
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic