• 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

Rounding in BigDecimal

 
Ranch Hand
Posts: 255
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I used the class BigDecimal and used the field ROUNDHALFUP in order to round up a number, but it didn't round up.
More specifically, the number was the double obtained by dividing 1942 by 40. If you divide 1942 by 40 on paper, you get 48.55 exactly, so I figured that using ROUNDHALFUP would give me 48.6 but instead I got 48.5.
I thought about it a bit, and I assume that dividing 1942.0 by 40.0 would give a double very close to 48.55, but not exactly because the numbers are all binary instead of base 10. Also, although 48.5 would be exact, 48.6 would not be exact.
What I used to do to round to the nearest tenth was like this:

double a;
double b;
double d = 10.0 * a/b + 0.5;
int result = (int) d;
// then change result into a string, stick a period in just before the last digit on the right, and add a zero on the left if necessary

You know what I mean, I think. But that takes up a lot of space in a program. Using BigDecimal saved space, but I got a result I did not want. There must be some simple way to round accurately to the nearest tenth. Anyone know what it is?
 
Marshal
Posts: 79239
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Are you using floating-point arithmetic? If you pass a double to the constructor of a BigDecimal you can permanently immortalise any arithmetical errors.

campbell@linux-pgix:~/java> java RoundDemo 1942 40
48.5499999999999971578290569595992565155029296875
campbell@linux-pgix:~/java> java RoundDemo 1942.0 40.0
48.5499999999999971578290569595992565155029296875
campbell@linux-pgix:~/java>

So you would actually round to 48.5, not 48.6.
 
Kevin Tysen
Ranch Hand
Posts: 255
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This is the actual line in my program:

writer.write((new BigDecimal(tts / nw)).setScale(2, BigDecimal.ROUND_HALF_UP).toString());

And tts and nw are both doubles.

What do you mean by floating point arithmetic? Is that a float instead of a double?
What do you mean by "immortalize"?

 
Campbell Ritchie
Marshal
Posts: 79239
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Both float and double use floating-point arithmetic, which is inherently imprecise (look at these FAQs (no 20) and links). So when you divide 1942.0 by 40.0 you don't get 48.55, but something slightly less, in fact 48.5499999999999971578290569595992565155029296875.
If you pass that double to the BigDecimal constructor, you make the imprecision immortal, make it permanent, preserve it for ever, maintain it until the application terminates, can't get rid of it. So the BigDecimal will have the value of 48.5499999999999971578290569595992565155029296875 not 48.55.

TryThat should come out as 48.55, and should round to 48.6.
And instead of new BigDecimal(123.456) which can be imprecise, write new BigDecimal("123.456"). The String representation of the number will be interpreted precisely as 123.456.
It says in the The API documentation that a BigDecimal stores its values as whole numbers, so its arithmetic can be precise, just as integer arithmetic is precise. Note what it says in the divide method about Exceptions and precision.
 
Greenhorn
Posts: 23
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


 
Kevin Tysen
Ranch Hand
Posts: 255
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I used the .divide(BigDecimal divisor, int scale, int roundingMode) method in class BigDecimal and it worked.
Thank you!
 
Campbell Ritchie
Marshal
Posts: 79239
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You're welcome
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic