【问题标题】:Stackoverflow error in this recursion此递归中的 Stackoverflow 错误
【发布时间】:2015-01-23 04:12:00
【问题描述】:

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

【问题讨论】:

    标签: java ruby recursion


    【解决方案1】:

    尝试将sum == 1000 更改为sum >= 1000。没有三元组的总和为正好 1000,所以它跳过了终止条件。

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        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。 而且,由于您使用递归,最终会发生堆栈溢出(如果您设法在没有递归的情况下解决问题,那将是一个无限循环)

        【讨论】:

          【解决方案4】:

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

          【讨论】:

            【解决方案5】:

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

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

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

            【讨论】:

              【解决方案6】:

              顺便说一句,你是乘以 2。您需要提高到 2 次方,所以是 a^2 或 a**2。

              我基于代码中的“pythagoreanTriples”这个词。

              【讨论】:

              • 没有。例如,3、4、5 和 6、8、10 都是毕达哥拉斯三元组,而 9、16、25 则不是。 a^2 + b^2 = c^2 是齐次的(所有项都具有相同的度数),并且对于所有此类方程乘以一个常数会得到另一个解。
              • 你的意思是什么?我知道三重是什么。可能会让您感到困惑的是,该算法不会验证三元组是否真的是这样,因此它永远不会对任何数字进行平方。它只知道 3, 4, 5 是三元组(你也知道,不是吗?)并且 3 * 2^n, 4 * 2^n, 5 * 2^n 也是。如果您的观点是该代码是该 ProjectEuler 问题的错误解决方案,请说明,然后注意您的提案并没有解决问题,它只会使事情变得更糟,因为它不会产生新的三元组。
              猜你喜欢
              • 2011-12-26
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-07-26
              • 1970-01-01
              • 2017-10-04
              相关资源
              最近更新 更多