有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

带有递归的java堆栈溢出异常

我正在尝试制作一个计算双阶乘的程序(示例-n=3,=>;(3!)!=6! = 720)但我在递归底部遇到了一些问题,并且出现了堆栈溢出异常

public static long df(long n) {
    if (n == 1) {
        return 1;
    } else {
        return df(n * df(n - 1));
    }
}

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

共 (4) 个答案

  1. # 1 楼答案

    我认为你应该在阶乘的帮助下使用相互递归

    一般的g-阶乘函数可以构成阶乘g次:

    public static long gf(long n, long g) {
        if (g == 1){
            return fact(n);
        }
        return fact(gf(n, g - 1));
    }
    

    具体的双阶乘可以是gf(n, 2)

    public static long df(long n) {
        return gf(n, 2);
    }
    

    阶乘辅助函数:

    public static long fact(long n) {
        if (n == 1) {
            return 1;
        } else {
            return n * fact(n - 1);
        }
    }
    

    现在测试:

    public static void main(String[] args) {
        System.out.println(df(3));
    }
    
  2. # 2 楼答案

    我们可以做到:

    public static long factorial(long n) {
        return (n <= 1) ? 1 : n * factorial(n - 1);
    }
    
    public static long twice_factorial(long n) {
        return factorial(factorial(n));
    }
    

    如果需要,通过一些技巧将其转化为单一方法:

    public static long twice_factorial(long n) {
    
        return new Object() {
            long factorial(long n) {
                return (n <= 1) ? 1 : n * factorial(n - 1);
            }
    
            long twice_factorial(long n) {
                return factorial(factorial(n));
            }
        }.twice_factorial(n);
    }
    

    但这是一个无用的函数,因为它只适用于n<;4--一旦我们到达(4!)!,我们超出了Java long类型的限制:

    (4!)! = 24! = 620,448,401,733,239,439,360,000
    Java 'long' +max  = 9,223,372,036,854,755,807
    

    如果希望此函数有用,可以使用浮动近似方程。但在近似值上再次调用近似阶乘可能没有多大意义。对于嵌套的阶乘值本身,需要一个浮动近似方程

    或者,我们可以切换到^{

    import java.math.BigInteger;
    
    public class Test {
    
        public static BigInteger factorial(BigInteger n) {
            return (n.compareTo(BigInteger.ONE) <= 0) ? n : n.multiply(factorial(n.subtract(BigInteger.ONE)));
        }
    
        public static BigInteger twice_factorial(BigInteger n) {
            return factorial(factorial(n));
        }
    
        public static void main(String[] args) {
            System.out.println(twice_factorial(new BigInteger(args[0])));
        }
    }
    

    用法

    > java Test 4
    620448401733239439360000
    >
    

    但这只涉及(7!)!在我们得到java.lang.StackOverflowError之前!如果我们想更进一步,我们需要转储递归并迭代计算阶乘:

    public static BigInteger factorial(BigInteger n) {
        BigInteger result = BigInteger.ONE;
    
        while (n.compareTo(BigInteger.ONE) > 0) {
            result = result.multiply(n);
    
            n = n.subtract(BigInteger.ONE);
        }
    
        return result;
    }
    

    用法

    > java Test 8
    34343594927610057460299569794488787548168370492599954077788679570543951730
    56532019908409885347136320062629610912426681208933917127972031183174941649
    96595241192401936325236835841309623900814542199431592985678608274776672087
    95121782091782285081003034058936009374494731880192149398389083772042074284
    01934242037338152135699611399400041646418675870467025785609383107424869450
    ...
    00000000000000000000000000000000000000000000000000000000000000000000000000
    00000000000000000000000000000000000000000000000000000000000000000000000000
    00000000000000000000000000000000000000000000000000000000000000000000000000
    000000000000000000000000000000000000000000
    > 
    
  3. # 3 楼答案

    首先,定义阶乘函数:

    通过Jupyter:

    #include <iostream>
    std::cout << "some output" << std::endl;
    
    long fac(long n) {
        if( n == 1)
            return 1;
        else
            return n * fac((n-1));
    }
    

    在定义函数之后:

    long double_fac(long n)
    {
        long step_one = fac(n);
        return fac(step_one);
    }
    

    Factorielle-Algorythme

  4. # 4 楼答案

    你遇到了一个无限循环df(n * df(n - 1));

    n * df(n-1)将计算阶乘,而您无意中将答案反馈回递归方法,导致它永远持续下去

    改变

    return df(n * df(n - 1));
    

    return n * df(n - 1);
    

    对于阶乘,你应该得到正确的结果


    一旦有了这个有效的递归阶乘方法,只需使用df(df(3))就可以更容易地创建双阶乘