【问题标题】:Stack overflow exception with recursion递归堆栈溢出异常
【发布时间】:2016-02-19 09:42:45
【问题描述】:

我正在尝试制作一个计算双阶乘的程序(example - 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));
}

【问题讨论】:

  • 小心术语,double factorial 有一个特定的含义,其中n!! 是从 1 到 n 共享相同奇偶校验的数字的乘积(奇数/偶数) ) 为n。您想要做的更像是 nest 调用阶乘。

标签: java recursion


【解决方案1】:

您遇到df(n * df(n - 1)); 的无限循环

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

改变

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

return n * df(n - 1);

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


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

【讨论】:

  • 您建议的解决方案递归地计算阶乘 - 3! = 6。但我正在尝试计算这个(3!)! = 6! = 720。我试图递归计算阶乘两次。
  • @NoSuchUserException 看起来没有一种方法可以很好地做到这一点,但仅使用 df(df(input)) 应该可以满足您的需求
  • @phflack 谢谢!
【解决方案2】:

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

一般的g-factorial函数可以合成阶乘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));
}

【讨论】:

    【解决方案3】:

    我们可以做到:

    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 long 类型的限制:

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

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

    或者,我们可以切换到BigInteger

    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
    > 
    

    【讨论】:

      【解决方案4】:

      首先,定义你的阶乘函数:

      通过 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

      【讨论】:

        猜你喜欢
        • 2018-03-25
        • 2017-09-27
        • 1970-01-01
        • 2010-12-07
        • 2020-12-17
        • 2018-07-24
        • 2010-11-27
        • 2015-04-04
        相关资源
        最近更新 更多