此递归中出现 Stackoverflow 错误

发布于 2024-09-19 17:57:24 字数 914 浏览 11 评论 0原文

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

What's wrong with this recursion in 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);
        }
    }
}

I get this exception:

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

When I try to do the same in Ruby, I get this:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

落日海湾 2024-09-26 17:57:24

尝试将 sum == 1000 更改为 sum >= 1000。没有三元组的总和恰好为 1000,因此它会跳过终止条件。

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

Try changing sum == 1000 to sum >= 1000. There is no triple that sums to exactly 1000, so it's skipping over the terminating condition.

Also, your Ruby code doesn't match your Java code (you're missing else). Even if it did find a sum of 1000, it would print the message, and keep recursing until it crashed.

向日葵 2024-09-26 17:57:24

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

Well, if you look at your method that performs the recursion, the only exit condition is when sum == 1000. Your current input values are 3, 4, and 5. That sum is 12. The condition doesn't hold true, so it tries the next set, where sum = 24. Then 48, 96 and so forth. The sum will never be 1000, so the recursion will never end.

じее 2024-09-26 17:57:24

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+4+5 is 12.

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

12*2*2 = 12*4

Now, let's see: Your program will stop when the sum equals 1000.
That will never happen, the sequence will be:

12 24 48 96 192 384 768 1536 ...

Unless some sort of integer overflow rescues you, you will never reach 1000.
And, since you are using recursion, eventually a stack overflow happens(if you managed to solve the problem without recursion, it'd be an infinite loop)

吃→可爱长大的 2024-09-26 17:57:24

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

Well, you construct infinite recursion here, without anything to stop it. Sure it breaks with an error of stack being full.

抽个烟儿 2024-09-26 17:57:24

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

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

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

Beyond the bug in your code which other answers have described, using recursion in Java in this way is problematic anyway. You are using tail recursion, so the compiler or the JVM could convert the call to a jump to the beginning of the procedure and consume no stack space; however, this is not done (to preserve accurate stack traces).

E.g., processing a list in such a way in Java would cause your code to be limited to processing only lists of limited length before a stack overflow, and even when it works you would get slower performance and higher memory consumption. But the possibility of a crash (for say more than 1-10 million elements, since the stack is by default 8MiB) is more important.

If you were to program in Scala you, or other functional languages, that style would be appropriate and efficiently supported.

月竹挽风 2024-09-26 17:57:24

顺便说一下,你正在乘以二。您需要计算 2 次方,即 a^2 或 a**2。

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

By the way, you are multiplying by two. You need to raise to the power two, so a^2 or a**2.

I'm basing this on the word "pythagoreanTriples" in the code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文