-4

I have a simple calculation on double values in a java program.

double blockNetMoney=1239891.632;
double blockQty=1120000;
double allocQty=150000;
BigDecimal allocNetMoney = new BigDecimal(String.valueOf((allocQty/blockQty)*blockNetMoney));
System.out.println("AllocNetMoney:"+allocNetMoney );

I'm getting a value 166056.91499999998 for Alloc Net money. But correct value is 166056.915 and i get that value when i use a calculator or excel.

Can you please suggest what changes i need to make to get the value 166056.915

keshlam
  • 7,931
  • 2
  • 19
  • 33
  • 3
    Java is often wrong. It's only been around for 1995, give it some time. – Sotirios Delimanolis Jan 22 '14 at 04:21
  • 1
    You would find this useful: [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) – Christian Tapia Jan 22 '14 at 04:22
  • 1
    This is due to floating point precision (spoiler alert: there's not infinite precision). See http://floating-point-gui.de. For money, you should use some sort of decimal representation (floats are binary), like `BigDecimal` or `int` (with values representing cents instead of dollars, or tenths of a cent, etc). – yshavit Jan 22 '14 at 04:23
  • Try looking at this question/answer: http://stackoverflow.com/questions/5710394/round-double-to-two-decimal-places-in-java – Mike Koch Jan 22 '14 at 04:25
  • @MikeKoch: that's not a good duplicate. It's not about the same thing – Jeroen Vannevel Jan 22 '14 at 04:26
  • @Christian Respectfully, I think that's the wrong thing to point floating-point newbies to. (I know everyone uses it, so this isn't a dig at you personally.) It's great information... once you grok the basic idea. I think the floating-point-gui.de site is much more newbie-friendly (despite looking like a German site about GUI). – yshavit Jan 22 '14 at 04:29
  • 1
    @yshavit just posted as a useful link. In fact, I've just started reading it. Thanks for providing that link, it looks a lot more friendly. – Christian Tapia Jan 22 '14 at 04:33
  • 1
    General tip: If you think a tool that everyone else is using without problems is "wrong" on something that's so basic that everyone else must be using it... you're probably wrong. It's a lot safer (and more productive, and more likely to get good answers, and less likely to be downvoted) to just present the facts and ask for an explanation, rather than to make the assertion. – keshlam Jan 22 '14 at 04:37
  • 1
    @Christian I totally understand, and I hope I wasn't coming off as attacking you! The one you posted is definitely a great followup to a gentle introduction. :) – yshavit Jan 22 '14 at 04:47

1 Answers1

1

What Every Computer Scientist Should Know About Floating-Point Arithmetic.

There are many values which cannot be precisely expressed under IEEE-54 storage. One solution for greater precision is to use java.math.BigDecimal and a java.math.MathContext through-out for example -

BigDecimal blockNetMoney = new BigDecimal(
    "1239891.632");
BigDecimal blockQty = new BigDecimal("1120000");
BigDecimal allocQty = new BigDecimal("150000");
BigDecimal allocNetMoney = allocQty.divide(
    blockQty, new MathContext(10)).multiply( // <-- 10 digits of precision
    blockNetMoney, new MathContext(9));      // <-- 9 digits of output.
System.out.println("AllocNetMoney:"
    + allocNetMoney);

Outputs

AllocNetMoney:166056.915
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249