为什么我使用递归会出现这个错误?

How come I got this error by using recursion?

如果我输入 33333,我会收到此错误。我检查了很多次,但我不知道如何解决。如果我输入大于 33333 的数字,它工作正常。 33333 怎么了?

我的日志:

Exception in thread "AWT-EventQueue-0" java.lang.WhosebugError
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)
at piande.PiandE.factorial(PiandE.java:67)

我的代码:

private double factorial(long number) {
    if (number <= 1) {         // if number is smaller of eaqual to 1 then return directly
        return 1; //factorial of 1 is 1
    } else {
        return number * factorial(number - 1); //using recursion to reuse the method until number be 1
    }
}

不要使用递归,使用循环。 每次调用一个方法,栈都会增长,最后会变满,这就是为什么说栈溢出。

所以当你认为递归会多次调用同一个方法时,不要使用递归

递归是计算阶乘的一种极其低效的方法,不幸的是,它也被用于几乎所有编程课程的递归介绍中。尝试使用迭代方法!

当我测试它时(当然,在 C# 而不是 Java 中,但语法相同并且它的行为方式相似)我得到了所有相似值的相似错误 - 只是那个特定的数字。

请记住,每次进行递归调用时,堆栈都会增加,因此通常情况下,如果递归调用过多,您最终会 运行 [=22] =] 仅仅是因为栈变得太大了。

记忆(这需要存储中间结果,这样程序就不必采取那么多步骤;例如,如果你知道 10,000!,你可以在更大的值上保存数千次计算)可以改善这种情况,可以使用尾递归(在支持它的语言中)或者等效地使用 "for" 循环(根本不会增加堆栈)。

还要记住,阶乘最终会变得比 long 或 double 类型所能表示的还要大,因此堆栈溢出异常不会是表示它们的唯一问题。

您的代码超出了堆栈限制,但您可以 "unroll" 递归的一部分。如果您还使用 BigInteger ,则可以计算出非常大的结果。像,

private static BigInteger factorial(long number) {
    if (number <= 1) {
        return BigInteger.ONE;
    } else if (number > 7) {
        return BigInteger.valueOf(number)//
                .multiply(BigInteger.valueOf(number - 1))//
                .multiply(BigInteger.valueOf(number - 2))//
                .multiply(BigInteger.valueOf(number - 3))//
                .multiply(BigInteger.valueOf(number - 4))//
                .multiply(BigInteger.valueOf(number - 5))//
                .multiply(BigInteger.valueOf(number - 6))//
                .multiply(factorial(number - 7));
    } else {
        return BigInteger.valueOf(number).multiply(factorial(number - 1));
    }
}

我运行和

public static void main(String args[]) {
    System.out.println(factorial(33333));
}

如前所述,结果有点大 post。