【问题标题】:why do i get java.lang.StackOverflowError here?为什么我会在这里得到 java.lang.StackOverflowError?
【发布时间】:2012-03-13 13:51:12
【问题描述】:

_以下问题的以下程序给出了一系列异常Exception in thread "main" java.lang.StackOverflowError at testing_package.Compute.factorial(Compute.java:105)我不明白为什么会出现这个错误。

问题:N个男孩和M个女孩正在剧院学习表演技巧。表演一出戏 他们需要组成一个包含不少于4个男孩和不少于1个女孩的P演员组。这 剧院要求你编写一个程序,告诉他们可以组成小组的方式数量。 注意:组合应该是唯一的,而不是组合的顺序。

import java.io.*;

class Compute {

private static int NFact;
private static int N_Minus_R_Fact;
private static int RFact;
private static int fact=0;

public static int readTheStrengthOfGroup() {
    int strengthOfGroup=0;
    try {
        System.out.println("Enter the strength of group : ");
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String read = reader.readLine();
        strengthOfGroup = Integer.parseInt(read);
    } catch(Exception exc) {
        System.out.println(exc);
      }
      return strengthOfGroup;
}

public static int readTheNumberOfBoys() {
   int boysToParticipate=0;
   try {
    System.out.println("Enter the number of boys to participate in the play : ");
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    String read = reader.readLine();
    boysToParticipate = Integer.parseInt(read);
   } catch(Exception exc) {
        System.out.println(exc);
     }
    return boysToParticipate;
}

public static int readTheNumberOfGirls() {
    int girlsToParticipate=0;
    try {
        System.out.println("Enter the number of girls to participate in the play : ");
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String read = reader.readLine();
        girlsToParticipate = Integer.parseInt(read);
    } catch(Exception exc) {
        System.out.println(exc);
      }
    return girlsToParticipate;
}

public static int compute(int strengthOfGroup , int boysToParticipate , int girlsToParticipate) {
    if( boysToParticipate < 4 || girlsToParticipate < 1) {
        return 0;
    } else {
        /*  P >= 5 
         *  N : Boys
         *  M : Girls
         *  result = M+N C P - { (N C 0)(M C P)+(N C 1)(M C P-1)+(N C 2)(M C P-2)+(N C 3)(M C P-3)+(N C P)(M C 0) }
         */
         int resultP_2 = 0;
         int totalNumberOfParticipants = boysToParticipate + girlsToParticipate;
         int totalNumberOfParticipants_C_strengthOfGroup = computeFactorial(totalNumberOfParticipants , strengthOfGroup);
         for( int i = 0 ; i <= 4 ; i++ ) {
                          if( i == 4 ) {
                resultP_2 = resultP_2 + (computeFactorial(boysToParticipate,strengthOfGroup) * computeFactorial(girlsToParticipate,0)); 
            }else {
            resultP_2 = resultP_2 + (computeFactorial(boysToParticipate,i) * computeFactorial(girlsToParticipate,strengthOfGroup));
            strengthOfGroup--;}
         }
         int result = totalNumberOfParticipants_C_strengthOfGroup - resultP_2;
         return result;
      }
}

public static int computeFactorial(int N , int R) {
    if(R > N) {
        throw new RuntimeException("Invalid Parameters");
    } else {
        /* int NFact;
        int N_Minus_R_Fact;
        int RFact; */
        NFact = factorial(N);
        N_Minus_R_Fact = factorial(N-R);
        RFact = factorial(R);
        return( NFact / ( N_Minus_R_Fact-RFact ) );

      }
}

public static int factorial(int num) {
    if( num == 1 ) {
        return 1;
    } else {
        fact = num * factorial(num-1); // LINE 105
        return fact;
      }
}

public static void main(String args[]) {
    int strengthOfGroup = readTheStrengthOfGroup();
    int boysToParticipate = readTheNumberOfBoys();
    int girlsToParticipate = readTheNumberOfGirls();
    int result = compute(strengthOfGroup , boysToParticipate , girlsToParticipate);
    System.out.println("Number of groups that can be formed : " + result);
}

}

我已经注释了第 105 行。

【问题讨论】:

  • 你贴的代码有103行,有问题的行(105)在哪里?
  • 因为您使用的是递归方法。要解决这个问题,无论是改进代码还是增加堆栈大小。

标签: java exception recursion stack-overflow factorial


【解决方案1】:

computeFactorial 避免在R &gt; N 的情况下调用factorial,但在所有其他情况下调用它(R == N、R &lt; N),传入N-R。如果R == N,那么N-R 就是0。在factorial 中,您正在检查num == 1 是否并返回1,但是当num 是0 时,您将让factorial 使用num - 1 调用自身,即-1。然后它再次使用num - 1 调用自身,即-2,以此类推,使用越来越大的负数(-1,-2,...),直到你用完堆栈。

我没有仔细阅读代码,但至少你需要让factorial 在num == 0 以及num == 1 (0! = 1) 时返回1。如果你给它一个负数,我也会让它抛出一个异常。

【讨论】:

  • @SuhailGupta:基本上,不要将负数传递给factorial,并单独更正factorial,以便它接受0并返回正确的结果(0! = 1就像@987654351一样@)。如果您确实将负数传递给factorial,我可能还会抛出异常。我不是数学家,但我认为您不能对负数进行阶乘;我敢肯定你不能用通常的n! = n * (n - 1) 公式。
  • 这个答案大部分是正确的——你有时会调用阶乘(0)。由于递归在 1 处停止,这永远不会是好的。如果您将第 102 行从 if( num == 1 ){ 更改为 if( num == 0 ){,您的堆栈溢出问题就会消失。关于R &gt; N 的部分无关紧要——你已经正确地完成了这部分。但是你还有一个错误 - 写着return( NFact / ( N_Minus_R_Fact-RFact ) ); 的那一行应该写着return( NFact / ( N_Minus_R_Fact * RFact ) );。另外,如果你想让代码更高效,...(继续评论)...
  • 建立一个阶乘数组,从 0 开始!并上升到您需要的最大阶乘。不要使用递归来填充它;只需将每个结果乘以正确的数字即可获得下一个结果。然后,在计算中,每次需要阶乘时,只需将其从数组中拉出,而不是重新计算。
  • @DavidWallace:谢谢,最初我认为这只是0 的情况,他弄错了,但后来我想到他(最初)也以否定的方式称呼它数字。但你是对的,保护条件R &gt; N 是正确的。我已经修复了答案的那一部分。
猜你喜欢
  • 2011-01-21
  • 2020-07-31
  • 2021-11-08
  • 2016-11-22
  • 2015-10-25
  • 1970-01-01
  • 2016-09-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多