简体   繁体   English

使用递归的StackOverflowError

[英]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. 教授还希望当迭代器等于10,100,1000等时,以毫秒为单位对迭代进行计时。我虽然可以正常工作,但是在C ++获取计时器方面遇到了很多麻烦,所以我改用Java了,更容易获得毫秒输出。

But now when I try to use any number over 8,000 I get a big fat stack overflow error from the Recursive algorithm. 但是现在当我尝试使用超过8,000的任何数字时,我从递归算法中得到了一个很大的胖堆栈溢出错误。 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. 您的特殊问题是您尝试执行8000级递归,因为每个级别只会递减值。 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). 您可以考虑使用-ss-oss选项来增加JVM的堆栈大小(当然取决于实现)。 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: 在安排整个递归操作的时间方面,我只需将顶级调用之前的时间存储在main() ,然后将其与顶级调用返回的时间进行比较,例如:

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. 如果你想递归调用在某些点上做到这一点,你可以初始化一个“全局”计数器变量(一个递归本身,如类级别静态变量外)为0,并有递归函数增加它的每递归级别。

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. 然后让它在您感兴趣的点输出时间变化量,例如变量设置为10、100、1000等时。

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));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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