Search code examples
javarecursionstack-overflowmathematical-optimization

Java programme to compute the nested radical constant


[Image from MathWorld, WolframAlpha

Using the code below I was able to estimate it upto: 1.7579327566180045

public class Sum {
static int count = 0;
static double a = 0;
public static void main(String[] args) {
    int x = 0;
    System.out.println(sum(x));
}

public static double sum(int x){
    count++;
    x++;
    if (count == 11000){
        return a;
    }
    return a = Math.sqrt(x+sum(x));
}

I am however not able to get an answer with more accuracy with the recursion here. Increasing the number of recursive calls from 11,000 gives me a StackOverflowError. I also looked up how I could use the java's BigDecimal here, but I'm unable to implement it here and honestly not sure if that would help.

Question :- how can I make this programme compute the constant to more decimal places and more accurately? I'm not certain if this I can compute it iteratively or not either. I wasn't able to work out an iterative definition.

In addition, I looked into Java 8 Streams too, but those didn't make much sense to me (since i'm new to programming and Java) and not sure if that is applicable here.

Thanks for any help!


Solution

  • If your only problem is the stack: don't use recursion, just use a plain iteration.

    If we call the iteration limit n, then the radical constant is:

    sqrt(1 + sqrt(2 + sqrt(3 + sqrt(4 + ... sqrt(... + sqrt(n))...))))
    

    which is the same as:

    sqrt(...(sqrt(sqrt(sqrt(n) + (n-1)) + (n-2)) + (n-3)) + ... )
    

    So let's just use that:

    public class Test {
      public Test(int iterations) {
        int n = iterations;
        double sum = 0;
        while (n > 0) {
          sum = Math.sqrt(sum + n--);
        }
        System.out.printf("Precision using %d iterations: %1.50f\n", iterations, sum);
      }
    
      public static void main(String[] args) {
        new Test(1);
        new Test(10);
        new Test(100);
        new Test(1000);
        new Test(10000);
        new Test(100000);
        new Test(1000000);
        new Test(10000000);
        new Test(100000000);
      }
    }
    

    Of course, since you want precision, this isn't going to help much: now you're no longer running into a stack issue, you're running into the fact that IEEE floating point numbers are not for mathematically precise computation:

    Precision using 1 iterations: 1.00000000000000000000000000000000000000000000000000
    Precision using 10 iterations: 1.75793261139383100000000000000000000000000000000000
    Precision using 100 iterations: 1.75793275661800450000000000000000000000000000000000
    Precision using 1000 iterations: 1.75793275661800450000000000000000000000000000000000
    Precision using 10000 iterations: 1.75793275661800450000000000000000000000000000000000
    Precision using 100000 iterations: 1.75793275661800450000000000000000000000000000000000
    Precision using 1000000 iterations: 1.75793275661800450000000000000000000000000000000000
    Precision using 10000000 iterations: 1.75793275661800450000000000000000000000000000000000
    Precision using 100000000 iterations: 1.75793275661800450000000000000000000000000000000000
    

    As per the official documentation:

    This data type should never be used for precise values, such as currency. For that, you will need to use the java.math.BigDecimal class instead. Numbers and Strings covers BigDecimal and other useful classes provided by the Java platform.