简体   繁体   中英

StackOverflowError using Recursion

I'm supposed to be comparing a Recursive and a Non-Recursive function to see which one is quicker for a class project. The professor also wants us to time the iterations in milliseconds when the iterator is equal to 10,100,1000, etc. I got it all to work but was having loads of trouble in C++ getting the timer, so I switched to Java as it's much much easier to get millisecond output.

But now when I try to use any number over 8,000 I get a big fat stack overflow error from the Recursive algorithm. Can anyone give me any insight? Bonus: I also can't figure out how to do the timer in the Recursive function like I did in the Non-Recursive. How would I approach this?

public class comparingTimes {
    public static void main(String[] args) {

        double num = 10000;
        double result;
        nonRec(num); 
        result = rec(num);      
        System.out.printf("Rec %.0f",(result));
    }
    public static void nonRec(double num)
    {
    double resultNum = 1;
    double total = 0;
    long startTime = System.currentTimeMillis();
    long endTime;
    for (double i = 1; i < num; i++)
     {
        total += i * (i+1);
        if (i == resultNum)
        {
            endTime = System.currentTimeMillis();
            System.out.printf("Total execution time: %f seconds - num = %.0f%n", (endTime - startTime)/1000.0, i);
            resultNum *= 10;
        }           
     }      
    System.out.printf("NonRec: %.0f%n", total); 
}
public static double rec(double num)
{
    if (num == 0)
        return 0;
    else            
        return num * (num-1) + rec(num-1);      
}
}

The ideal use case for recursion is when you reduce the "search space" massively on each recursion level. For example, consider a binary search where each recursion level halves the remaining search space.

Your particular problem is that you're trying to do 8000 levels of recursion since each level simply decrements the value. That's going to require a fairly large chunk of stack space.

You can look into increasing the stack size for your JVM with the -ss or -oss options (depending on implementation, of course). But that will only buy you so much.

In terms of timing the whole recursive operation, I would simply store the time before the top-level call in main() , then compare that to the time after that top-level call returns, something like:

long startTime = System.currentTimeMillis();
result = rec(num);
long endTime = System.currentTimeMillis();
// Now calculate the elapsed time.

There's no need to try and do it within the recursive call itself.

If you want to do it at certain points within the recursive call, you can initialise a "global" counter variable (one outside the recursion itself, such as a class-level static variable) to 0 and have the recursive function increment it for every recursion level.

Then have it output the time deltas at the points you're interested in, such as when the variable is set to 10, 100, 1000 and so on.

Try increasing the stack size .

As for measuring time

public static void main(String[] args) {

    double num = 10000;
    double result;
    long start = System.currentTimeMillis();
    nonRec(num); 
    long finish = System.currentTimeMillis();
    System.out.println("Time taken (non-recursive): " + (finish -start));
    start = System.currentTimeMillis();
    result = rec(num);      
    finish = System.currentTimeMillis();
    System.out.println("Time taken (recursive): " + (finish -start));
    System.out.printf("Rec %.0f",(result));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM