1

I am writing a recursive formula and require values when the function has run hundreds of times. At near the 450th - 500th run, the console outputs infinity.

Is it possible to force Java to output a larger value but in scientific notation?

Recursion:

public static void main(String[] args) {
    for (int i = 0; i < 500; i++) {
        System.out.println(Math.pow(3 + 2 * Math.sqrt(2), i)
                + Math.pow(3 - 2 * Math.sqrt(2), i));
    }
}

Output at roughly 450th run:

2.4705373096084562E302
1.4399346668019402E303
8.392554269850795E303
4.891539095230283E304
2.8509979144396616E305
1.661683357711494E306
9.685000354824998E306
5.644831877123849E307
Infinity
Infinity
Infinity
Infinity
Infinity
Infinity
Infinity
Infinity
Infinity

Edit

I have used BigDecimal, as recommended.

    for (int i = 0; i < 500; i++) {
        BigDecimal n = new BigDecimal(Math.pow(3 + 2 * Math.sqrt(2), i)
                + Math.pow(3 - 2 * Math.sqrt(2), i));
        System.out.println(n);
    }

However, now the console spits out :

Exception in thread "main" java.lang.NumberFormatException: Infinite or NaN
at java.math.BigDecimal.<init>(BigDecimal.java:808)
at mathC.Recursion2.main(Recursion2.java:9)

I have read that BigDecimal should be able to store a value that is roughly 8Gb of memory. Since my laptop contains 16Gb of 1600MHz memory, why is this happening? Is this number really 8Gb of memory?

The number before the error is (SO won't let me format this):

56448318771238491045438986070422562722375814412748377586799357549587081845130965398544956161588871436829847442988862310610370686259432485701530038671444090445069088383193741454463060427351807692569019541559990842957532377423388218307948475268885262237809144041880563122951075397138587894276020263963236237312

  • FYI, this is to study the behaviour of the recursive function in the code sample. – Jukebocks77 Mar 21 '14 at 21:33
  • 3
    You may want to look at Java's BigDecimal: http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html – merlin2011 Mar 21 '14 at 21:33
  • 4
    That is not a recursive method; `main` doesn't call itself. – rgettman Mar 21 '14 at 21:34
  • @rgettman yea you're right, this is not a method.. this is a `for-loop` running a function..@merlin okay I will check that out. Thanks. – Jukebocks77 Mar 21 '14 at 21:37
  • 1
    You're now just taking the `double` result, which has already overflowed, and converting it to a `BigDecimal`. You need to do the whole computation with `BigDecimal` to avoid the overflow. – Alan Stokes Mar 21 '14 at 22:08
  • I'd recommend looking again at the recursive form (`BigInteger` may help). Failing that: as you know, the result is always integral as the square root terms cancel out. Perhaps think about performing the power computations symbolically, simplifying as you go. – Alan Stokes Mar 21 '14 at 22:26
  • @AlanStokes My apologies, I have deleted my previous comment as `Real` is not included in the default java libraries. I will try your recommendation though. If not, then I guess I will be stuck analyzing only 400 numbers and not 500 :( – Jukebocks77 Mar 21 '14 at 22:36
  • 1
    Another alternative would be to compute the logarithm of the final answer - which will easily fit in a `double`. Depends what analysis you want to do, of course. – Alan Stokes Mar 21 '14 at 22:43
  • @AlanStokes The analysis actually requires a large amount of precision. I am essentially seeing how close this formula gets to an integer as `i` increases (b.c. 3+2(sqrt(2)) is irrational). I have figured it out using `BigDecimal` though. thanks. – Jukebocks77 Mar 22 '14 at 03:54
  • The answer is always exactly an integer, isn't it? The even terms of sqrt(2) are integral and the odd terms cancel out. (You can represent the values as an integer/BigInteger plus an integer multiple of sqrt(2), and then compute the results exactly.) – Alan Stokes Mar 22 '14 at 13:38

3 Answers3

4

Once the values get large enough, they exceed the maximum value that a double can store: Double.MAX_VALUE, or 1.7976931348623157E308. When such an operation exceeds this maximum value, then the double value Infinity results.

This is specified by the JLS, Section 15.18.2:

If the magnitude of the sum is too large to represent, we say the operation overflows; the result is then an infinity of appropriate sign.

(Other binary arithmetic operators have their own JLS Section, and they say the same thing.)

To get a bigger range, use a BigDecimal to store results with arbitrary precision.

rgettman
  • 176,041
  • 30
  • 275
  • 357
  • Perfect theoretical explanation. Here's a follow up link: [floating point standard](http://www.wikipedia.org/wiki/Double-precision_floating-point_format#IEEE_754_double-precision_binary_floating-point_format:_binary64) – Jean-Paul Mar 21 '14 at 21:38
  • Okay, i have implemented `BigDecimal` as recommended. However, an error now comes up, please see latest edit on question. – Jukebocks77 Mar 21 '14 at 21:58
  • 2
    It looks like your intermediate result is equal to your last scientific notation number - `5.644831877123849E307`. You're still performing `double` arithmetic before the value gets passed to a `BigDecimal`. Try performing all arithmetic operations using values that are already `BigDecimal`s, with `add`, `multiply`, and `subtract`. – rgettman Mar 21 '14 at 22:01
2

You could have a look at BigDecimal.

(That doesn't look very recursive, as Fibonacci algorithms go.)

Community
  • 1
  • 1
Alan Stokes
  • 18,815
  • 3
  • 45
  • 64
1

Well, I don't know what the goal of the program is, but if you just want it to print it (instead of re-using it in another operaton), why not using the International System for quick notation? That way, you only have to create an if statement with the desired range.

(Here's a link to a table with the values : http://ronblond.com/MathGlossary/Division03/International%20System%20of%20Units/PrefixChart.gif)

Not only it solves that issue (once again, if you merely want the output, and a non-exact one), but it's also easier on the eye.

---//--- Example (Edit) ---//---

Let's take 2222, thus, 1,10 and 1k. If on a cicle you divide it by a multiple of 10, you can in theory easily convert it. Let's see:

      // For cicle here with an increasing i. n is how many times you've divided
     if (i>999 && i<10000){    // if you have i=2222

    i=(i/(n*10));   // in this case, n=100 , thus the  integer i = 2
    System.out.println(i + "k");  // 2222 is aproximatly 2k

    }

Although, this would only work if you could actually create a way to stop the loop. Something that has only came up to me now.

Oak
  • 693
  • 7
  • 13
  • Internation System..? – Jukebocks77 Mar 21 '14 at 22:20
  • If you can't represent the answer, there's no way to print it. – Alan Stokes Mar 21 '14 at 22:21
  • Even though you can't represent it, you can (since the code is always increasing) divide it by a variable (which would be a multiple of 10), thus, once you reach a certain limit, the variable would be smaller (thus you can represent it) – Oak Mar 21 '14 at 22:45
  • @Alan Stokes, take a look at the awnser (I added an example), it solves the problem you created, although it creates a new one, which would render this cicle infinite. – Oak Mar 21 '14 at 22:54
  • @user3126359 I understand you now. So basically, when the answer becomes too large, convert it to a larger unit (thus making the number of digits smaller). Nice. Although I would lose precision which is needed in this case. – Jukebocks77 Mar 22 '14 at 03:52
  • Yes, that would be a an issue, but, should you only need a rounded up number, that it would work =) – Oak Mar 22 '14 at 17:55