【问题标题】:why am I getting stack overflow exception or a logic error every time; java为什么每次都会出现堆栈溢出异常或逻辑错误;爪哇
【发布时间】:2015-09-30 07:28:58
【问题描述】:

每当我尝试这个 for 循环时,都会出现堆栈溢出错误。目标是使用我编辑的二项式分布公式,因为它给我的数学结果不准确。这导致程序产生堆栈溢出错误。我改变了它,所以它编译了,但我希望二项式分布占概率总数的百分比。我遇到了逻辑错误。

  for (int numOfSuccesses = 0; numOfSuccesses <= numOfTrials; numOfSuccesses++){
        for(int i = 0; i <= numOfTrials; i++){
           total+=probability;
        }
        probability += factorial(numOfTrials)/(factorial(numOfTrials - numOfSuccesses)*factorial(numOfSuccesses));
     System.out.println("Probability of " + numOfSuccesses + " successes is: " + probability/total);
  }

我确定我是否有堆栈溢出是不正确的,但我想知道这个 for 循环是如何导致堆栈溢出的。另外,如果正确的公式固有地导致堆栈溢出,我该怎么办,我认为它可能会?中断语句?

这是逻辑错误:

输入试验次数:4 输入可能性的数量:5 0 成功的概率是:无穷大 1 次成功的概率是:1.0 2 次成功的概率为:0.36666666666666664 3次成功的概率是:0.17647058823529413 4次成功的概率是:0.1

我修复了异常,但我能得到的最好的就是这一行:

   if (n == 0){

在这个单独的阶乘函数中:

   public static int factorial(int n){
         if (n == 0){
            return 1;
         }else{
            return n * factorial(n - 1);
         }
      }
}

【问题讨论】:

  • 如果我不得不猜测,你有一个基于递归的简单实现 factorial。不过,如果您不想猜测,而是想要一个真正的答案,在您的帖子中包含异常!
  • 这段代码不足以说明导致溢出的原因。
  • 看到这段代码,我认为问题可能源于factorial(很可能是递归实现的)。请发布整个代码以及StackOverflowException 的堆栈跟踪。
  • 约翰·斯图尔特:如果你解决了这篇文章的问题,反对票可能会变成赞成票。
  • 注意:教科书喜欢使用阶乘函数来演示递归的工作原理。但在现实生活中,递归是一种不好的写法。请改用循环。

标签: java for-loop stack stack-overflow


【解决方案1】:

不,您的阶乘实现导致堆栈溢出,而不是循环。

我猜你写了一个不正确的递归阶乘方法。也许停止条件是错误的。

我也猜想你没有意识到幼稚的阶乘实现是多么容易溢出和效率低下。

您应该研究伽马函数(伽马的自然对数会更好)和记忆。

您有两个因子的比率,这将是 ln(gamma) 实现的自然候选者。如果你不知道为什么,这里有一个提示:

ln(A/B) = ln(A) - ln(B)

【讨论】:

  • 虽然这个答案很可能是正确的,但我不明白为什么人们会发布答案,如果问题/问题不清楚......
  • 我认为问题很明确。答案是正确的。我不明白为什么低声望的巨魔认为刻薄的 cmets 比真正的答案更有帮助。
  • 算法太幼稚了,即使你用ln。溢出和精度损失的空间太大。仅仅因为数学使用阶乘,并不意味着你的算法应该。
【解决方案2】:

虽然这不是您的堆栈溢出问题的答案(我们没有足够的信息来回答这个问题),但我想指出,计算阶乘并不是计算二项式系数的最有效方法。除了效率低下,当数字太大时,您还会不必要地遇到整数溢出。

以C(11,5)为例:使用带有阶乘的公式,这是

     11!
------------
 5! (11-5)!

但是如果你扩展它,你会注意到许多因素抵消了:

1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 x 11
-------------------------------------------
1 x 2 x 3 x 4 x 5 x 1 x 2 x 3 x 4 x 5 x 6

你可以去掉两边的1..6个因素,离开

7 x 8 x 9 x 10 x 11
-------------------
1 x 2 x 3 x 4 x 5

实际上将因子倒序写在分子中效果更好:

11 x 10 x 9 x 8 x 7
-------------------
 1 x 2 x 3 x 4 x 5

因为您现在可以通过一个简单的循环来计算答案。以“1”作为产品开始。然后乘以 11 除以 1;乘以 10 除以 2;乘以 9 除以 3;乘以 8 除以 4;乘以 7 并除以 5。(除法总是偶数 - 没有分数,因为您连续计算 C(11,1)、C(11,2)、C(11,3) 等)。我会把它留给你来计算循环的细节。 (请注意,这种方法可以很好地计算 C(n,0)。此外,为了提高效率,请注意 C(n,m) = C(n,nm); 因此您可以计算其中一个并获得相同的结果,你应该选择循环更短的那个。)

这减少了整数溢出的机会。如果您使用阶乘计算C(n,m),则n 的值!可能太大而无法放入long,即使答案适合并且上述算法不会遇到溢出问题。 (例如,21! 太大而无法放入 long。但是,C(21,10) = 352716 并且可以仅使用 ints 来计算。)

注意:在我开始输入后,问题似乎发生了重大变化,因此它可能无法解决问题的最新版本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-18
    • 2014-05-04
    • 2011-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多