修复Java中的StackOverflower错误

修复Java中的StackOverflower错误,java,recursion,stack-overflow,Java,Recursion,Stack Overflow,我对stacks有点陌生,所以我不太确定我是否完全理解StackOverflowerr所包含的内容。我确实读过,它主要发生在永不结束的递归中 public double calculateLeibniz(double pi, double x, long l) { if (l == 10000) { return pi; } if (l % 2 == 0) { pi -= (1.0/x); return calculateL

我对stacks有点陌生,所以我不太确定我是否完全理解StackOverflowerr所包含的内容。我确实读过,它主要发生在永不结束的递归中

public double calculateLeibniz(double pi, double x, long l) {
    if (l == 10000) {
        return pi;
    }
    if (l % 2 == 0) {
        pi -= (1.0/x);
        return calculateLeibniz(pi, x + 2.0, l + 1);
    } else {
        pi += (1.0/x);
        return calculateLeibniz(pi, x + 2.0, l + 1);
    }
}

我试图用莱布尼兹方法计算π,我想我应该试着调整我的递归肌肉。我不确定为什么它会返回错误,因为该方法设置为在10000次迭代后终止。使用循环会更有效,这本身是否存在错误?

10000是一个相当深的堆栈!JVM无疑是在你达到“极限”之前爆炸出来的。我建议您迭代地而不是递归地重新实现您的方法。像这样的

public double calculateLeibniz(double pi, double x, int l) {
    while (l < 10000) {
        if (l % 2 == 0) {
            pi -= 1.0/x;
        } else {
            pi += 1.0/x;
        }
        x += 2.0;
        ++l;
    }
    return pi;
}
public double calculateLeibniz(双pi,双x,int l){
而(l<10000){
如果(l%2==0){
pi-=1.0/x;
}否则{
pi+=1.0/x;
}
x+=2.0;
++l;
}
返回pi;
}

在这种情况下,您的算法的堆栈深度非常浅:具体来说是1个堆栈帧深度。

是的,您正在递归10000次,这意味着您正在构建一个包含所有10000个调用的堆栈。避免递归的一个原因正是因为它做到了这一点,如果堆栈空间不足,代码将失败——这显然是正在发生的事情。递归不必是无限的,只要足够大,堆栈空间就会用完,这并不一定意味着递归没有结束。您的内存可能无法处理太多的迭代。尝试在100之后终止,看看这是否修复了错误递归通常是一个猴子解决方案。像你这样的情况也可以通过迭代轻松解决。出于某种奇怪的原因,一些教育工作者坚持用数学上递归定义的问题来演示递归,而这些问题最好通过迭代来解决。这是一个遗憾,因为计算机科学中有许多问题本质上是递归的,递归非常适合于这些问题。scheme或其他尾部递归语言中的相同递归解决方案可以很好地工作。因为我们的语言没有对递归进行优化,所以我们很快就会对递归进行优化。