4

I am new to BigDecimal.
I tried some math calculations using Java code. When I try the same calculations using Google calculator it gives me a slightly different results. Which one is the most accurate?. If Google calculator is more accurate, then how to improve java code to match it?.

On Google calculator:

134.23576185216913 - (134.23576185216913 × √(1 - (200000000^2 ÷ 299800000^2))) = 34.2357618522

On Java:

      BigDecimal t1 = new BigDecimal(134.23576185216913);
      BigDecimal one = new BigDecimal(1);
      BigDecimal speed = new BigDecimal(200000000).pow(2);
      BigDecimal lightsSpeed = new BigDecimal(299800000).pow(2);

      MathContext mc = new MathContext(2, RoundingMode.HALF_UP);
      System.out.println(t1.subtract((t1.multiply(SquareRoot.bigSqrt(one.subtract(speed.divide(lightsSpeed,mc)))))));

The method of bigSqrt is from here

The result is:

run: 34.683856455950090090043113321827989040137639817587194953722595479211000578082422197809603912048352550091209304856567024386365147605287692511973841869226169664820176852861655846233912503305984796190828666994508412096618025960010635831985100961879858807909056676663493607611105279976694118991120829708264297254294821755138400476425886154174804687500
BUILD SUCCESSFUL (total time: 0 seconds)

Community
  • 1
  • 1
Saleh Feek
  • 2,048
  • 8
  • 34
  • 56
  • It may be helpful to reduce this down to the smallest portion which still shows the difference. For example, I imagine the loss isn't in the subtraction, you can probably remove that piece and still see the difference. The simplest case is always easiest to debug. – James Montagne May 12 '14 at 14:54
  • 1
    Eventhough you use a `BidDecimal`, you construct it with a `double` literal: `134.23576185216913`. Precision changes begin right there. where do you get `134.23576185216913` from? Can this be preresented as a fraction? That may yeild better results. – Nivas May 12 '14 at 14:55
  • And where is the `SquareRoot` class from? – Nivas May 12 '14 at 14:56
  • @Nivas I wrote an Empty class `SquareRoot` to add `bigSqrt` method to it from [here](http://stackoverflow.com/a/17306433/1576401) – Saleh Feek May 12 '14 at 15:14

2 Answers2

7

This is your issue:

MathContext mc = new MathContext(2, RoundingMode.HALF_UP);

your are rounding the division to 2 decimal places. Use MathContext mc = new MathContext(15, RoundingMode.HALF_UP); instead (for example) and you should get something closer to the expected result.

You can see the difference with:

System.out.println(speed.divide(lightsSpeed,new MathContext(2, RoundingMode.HALF_UP)));
System.out.println(speed.divide(lightsSpeed,new MathContext(15, RoundingMode.HALF_UP)));

which prints:

0.45
0.445037630156818

assylias
  • 321,522
  • 82
  • 660
  • 783
0

It is a bit unclear to me what is happening mathematically and in terms of data structures. To my understanding, BigDecimal can represent only certain rational numbers, by no means arbitrary square roots. The linked method in SquareRoot would return some approximation of the actual square root, which also seems to be the case from a superficial inspection of the code.

Codor
  • 17,447
  • 9
  • 29
  • 56