3

I am dividing two numbers 466489/249001 which results in Non-terminating decimal expansion.

As the BigDecimal class stores floating-point numbers with practically unlimited precision, I have gone for it.

    BigDecimal dividend = BigDecimal.valueOf(466489L);
    BigDecimal divisor  = BigDecimal.valueOf(249001L);
    System.out.println((double)466489/249001);
    //1.8734422753322275
    System.out.println(dividend.divide(divisor, MathContext.DECIMAL128));
    //1.873442275332227581415335681382806

From WolframAlpha I am getting the result as

1.87344227533222758141533568138280569154340745619495504034120344898213260187710089517712780269958755185722145694193999220...

So I suppose my result is precise.

Now I want to know how can I get more precision in my result using BigDecimal as calculated by WolframAlpha?

Zeeshan
  • 11,851
  • 21
  • 73
  • 98
  • Well you see where you're specifying `MathContext.DECIMAL128`? Have you tried specifying a `MathContext` with more decimal places? – Jon Skeet Mar 10 '14 at 11:49
  • @JonSkeet, I have tried `MathContext.UNLIMITED` but I am getting Exception _java.lang.ArithmeticException: Non-terminating decimal expansion_ – Zeeshan Mar 10 '14 at 11:53
  • Possible duplicate of [Maximum precision in BigDecimal](http://stackoverflow.com/questions/3990701/maximum-number-of-digits-after-the-decimal-point-using-bigdecimal). – Nader Ghanbari Mar 10 '14 at 11:54
  • 1
    Well yes, you would - as you said, it's a non-terminating decimal expansion. So you need to know what precision you need, and represent it that way. Either that, or just keep it as a fraction... – Jon Skeet Mar 10 '14 at 11:54
  • @Shaan since the expression is non-terminating you can't use `MathContext.UNLIMITED` otherwise you'd kill your VM. Provide a big enough limit and all should be fine. – Thomas Mar 10 '14 at 11:54
  • So if I use `new MathContext(1000, RoundingMode)`, which Rounding mode is more precise `HALF_UP` or `HALF_EVEN`? – Zeeshan Mar 10 '14 at 12:01
  • @Shaan that depends on your needs, the prefined contexts all use `HALF_EVEN` but I'd probably go with `HALF_UP` since according to the doc `HALF_EVEN` would round 2.5 to 2 which would not be what I'd expect. – Thomas Mar 10 '14 at 12:24

3 Answers3

3

You should be able to provide a MathContext instance with custom precision, e.g.

dividend.divide(divisor, new MathContext( 100 ) ); //whatever precision you need
Thomas
  • 87,414
  • 12
  • 119
  • 157
0

You could set scale with appropriate rounding to achieve this

System.out.println(dividend.divide(divisor,49,BigDecimal.ROUND_HALF_UP));

I get the following output : 1.8734422753322275814153356813828056915434074561950

user3182350
  • 21
  • 1
  • 3
0

Apart from the solutions posted by others involving using a MathContext there is always the possibility that a good Rational class may be useful.

See here for a good one.

You should maintain your number as a Rational to keep full accuracy and only render it into a decimal when saving it - at that point, of course, you will need to truncate again.

It is potentially possible to recover the inaccuracies - but not in a reliable way and it requires some maths. See here for my technique.

Community
  • 1
  • 1
OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213