此递归中的Stackoverflow错误

时间:2010-09-19 22:45:02

标签: java ruby recursion

Java 中的这种递归有什么问题?

public class findPyt
{
    public static int sum = 0;
    public static void main(String[] args)
    {
        findP(3, 4, 5);
    }

    public static void findP(int a, int b, int c)
    {
        sum = a+b+c;

        if (sum == 1000)
        {
            System.out.println("The Triplets are: "+ a +","+ b +","+ c);
        }
        else
        {
            findP(a*2, b*2, c*2);
        }
    }
}

我得到了这个例外:

Exception in thread "main" java.lang.StackOverflowError
    at hello.findP(hello.java:12)
    at hello.findP(hello.java:19)

当我尝试在 Ruby 中做同样的事情时,我得到了这个:

SystemStackError: stack level too deep


def pythagoreanTriples(a=3, b=4, c=5)

    if (a+b+c) == 1000
      puts "The Triplets are: "+ a +","+ b +","+ c
    else
    pythagoreanTriples(a*2, b*2, c*2)
    end
end

6 个答案:

答案 0 :(得分:12)

尝试将sum == 1000更改为sum >= 1000。没有三元素总和完全 1000,所以它正在跳过终止条件。

此外,您的Ruby代码与您的Java代码不匹配(您缺少else)。即使它确实找到1000的总和,它也会打印消息,并一直递归直到它崩溃。

答案 1 :(得分:3)

好吧,如果你看看执行递归的方法,唯一的退出条件是当sum == 1000时。你当前的输入值是3,4和5.这个总和是12.条件不成立是的,所以它尝试下一组,其中sum = 24.然后48,96等等。总和永远不会是1000,所以递归永远不会结束。

答案 2 :(得分:2)

3 + 4 + 5是12。

a * 2 + b * 2 + c * 2 =(a + b + c)* 2

12 * 2 * 2 = 12 * 4

现在,让我们看看:当总和等于1000时,您的程序将停止。 这将永远不会发生,顺序将是:

12 24 48 96 192 384 768 1536 ...

除非某种类型的整数溢出拯救你,否则你永远不会达到1000。 并且,由于您正在使用递归,最终会发生堆栈溢出(如果您设法在没有递归的情况下解决问题,那么它将是一个无限循环)

答案 3 :(得分:1)

好吧,你在这里构造无限递归,没有任何东西可以阻止它。当然,它会因堆栈错误而中断。

答案 4 :(得分:1)

除了代码中的其他答案所描述的错误之外,以这种方式在Java中使用递归仍然存在问题。您正在使用尾递归,因此编译器或JVM可以将调用转换为跳转到过程的开头并且不占用堆栈空间;但是,这没有做到(为了保持准确的堆栈跟踪)。

例如,在Java中以这种方式处理列表会导致您的代码仅限于在堆栈溢出之前仅处理有限长度的列表,即使它工作也会导致性能降低和内存消耗增加。但是崩溃的可能性(比如超过1-10百万个元素,因为堆栈默认为8MiB)更为重要。

如果您使用Scala或其他函数语言进行编程,那么该样式将得到适当且有效的支持。

答案 5 :(得分:0)

顺便说一下,你乘以2。你需要加强到2的幂,所以a ^ 2或a ** 2。

我的代码基于“毕达哥拉斯三重奏”这个词。