Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用递归的StackOverflowerr_Java_Recursion - Fatal编程技术网

Java 使用递归的StackOverflowerr

Java 使用递归的StackOverflowerr,java,recursion,Java,Recursion,我应该比较递归函数和非递归函数,看看哪一个对于类项目更快。教授还希望我们在迭代数等于101001000时,以毫秒为单位来迭代迭代。我把它全部都工作了,但是在C++中得到了很多麻烦,得到了定时器,所以我转换到java,因为它更容易得到毫秒输出。 但是现在,当我尝试使用任何超过8000的数字时,递归算法产生了一个很大的堆栈溢出错误。有人能给我一些见解吗? 另外:我也不能像在非递归函数中那样在递归函数中执行计时器。我将如何处理这个问题 public class comparingTimes {

我应该比较递归函数和非递归函数,看看哪一个对于类项目更快。教授还希望我们在迭代数等于101001000时,以毫秒为单位来迭代迭代。我把它全部都工作了,但是在C++中得到了很多麻烦,得到了定时器,所以我转换到java,因为它更容易得到毫秒输出。 但是现在,当我尝试使用任何超过8000的数字时,递归算法产生了一个很大的堆栈溢出错误。有人能给我一些见解吗? 另外:我也不能像在非递归函数中那样在递归函数中执行计时器。我将如何处理这个问题

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);      
}
}
公共类比较时间{
公共静态void main(字符串[]args){
双数=10000;
双重结果;
nonRec(num);
结果=rec(num);
System.out.printf(“Rec%.0f”,(结果));
}
公共静态无效NOREC(双数值)
{
双结果数=1;
双倍合计=0;
long startTime=System.currentTimeMillis();
长时间;
for(双i=1;i
递归的理想用例是在每个递归级别上大量减少“搜索空间”。例如,考虑一个二进制搜索,其中每个递归级别将剩下的搜索空间减半。 您的特殊问题是,您正试图执行8000个级别的递归,因为每个级别都会简单地递减值。这将需要相当大的堆栈空间

您可以考虑使用
-ss
-oss
选项来增加JVM的堆栈大小(当然,这取决于实现)。但那只能给你买这么多

就整个递归操作的计时而言,我只需将顶级调用之前的时间存储在
main()
中,然后将其与顶级调用返回后的时间进行比较,如:

long startTime = System.currentTimeMillis();
result = rec(num);
long endTime = System.currentTimeMillis();
// Now calculate the elapsed time.
无需尝试在递归调用本身中执行

如果要在递归调用中的某些点执行此操作,可以将“全局”计数器变量(递归本身之外的一个,例如类级静态变量)初始化为0,并让递归函数为每个递归级别递增它


然后让它在您感兴趣的点输出时间增量,例如当变量设置为10、100、1000等等。

递归的理想用例是在每个递归级别上大量减少“搜索空间”。例如,考虑一个二进制搜索,其中每个递归级别将剩下的搜索空间减半。 您的特殊问题是,您正试图执行8000个级别的递归,因为每个级别都会简单地递减值。这将需要相当大的堆栈空间

您可以考虑使用
-ss
-oss
选项来增加JVM的堆栈大小(当然,这取决于实现)。但那只能给你买这么多

就整个递归操作的计时而言,我只需将顶级调用之前的时间存储在
main()
中,然后将其与顶级调用返回后的时间进行比较,如:

long startTime = System.currentTimeMillis();
result = rec(num);
long endTime = System.currentTimeMillis();
// Now calculate the elapsed time.
无需尝试在递归调用本身中执行

如果要在递归调用中的某些点执行此操作,可以将“全局”计数器变量(递归本身之外的一个,例如类级静态变量)初始化为0,并让递归函数为每个递归级别递增它

然后让它在您感兴趣的点输出时间增量,例如当变量设置为10、100、1000等等。

尝试增加时间增量

至于测量时间

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));
}
试着增加压力

至于测量时间

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

拥有
==0
总是有风险的,这就是您在这里遇到的问题。将类型更改为
int
@BevynQ所有int值都可以用double表示。从表示整数的双精度中减去1不需要舍入。我认为问题更可能是堆栈空间。@Patrica:是的,你是对的。@PatriciaShanahan:总是正确的。恐怕这是你(BevynQ)必须习惯的。1+给Patricia。拥有
==0
总是有风险的,这就是你的问题所在。将类型更改为
int
@BevynQ所有int值都可以用double表示。从表示整数的双精度中减去1不需要舍入。我认为问题更可能是堆栈空间。@Patrica:是的,你是对的。@PatriciaShanahan:总是正确的。恐怕这是你(BevynQ)必须习惯的。1+致Patricia。只是好奇,教初学者使用递归编写阶乘正确吗?教递归的概念很好,这不是我在生产代码中会做的事情。阶乘是另一个缓慢减少搜索空间的问题。然而,对于阶乘,至少在溢出堆栈之前,您可能会溢出整数:-)递归是一个优雅的工具,但是,与真正的工具(锤子之类的工具)一样,您必须正确地定位作业。没有人想用十字螺丝刀砍倒一棵卡里树。我不知道哪一棵更糟。我宁愿让堆栈溢出,并得到问题的通知。1+用于伟大的讨论@帕西迪