为什么每次都得到堆栈溢出异常或逻辑错误; java

问题描述:

每当我尝试这个for循环,我得到一个堆栈溢出错误。目标是使用我编辑的二项分布公式,因为它给了我不准确的数学结果。这导致程序生成堆栈溢出错误。我改变它以便编译,但我希望二项分布占总概率总数的百分比。我收到逻辑错误。我确定它是不正确的,不管我是否有堆栈溢出,但我想知道这个for循环是如何导致堆栈溢出。另外,如果正确的公式本身导致堆栈溢出,我认为它可能会怎么办?突破声明?为什么每次都得到堆栈溢出异常或逻辑错误; java

这里的逻辑错误:

输入试验次数:4 输入的可能性的数目:5 概率的0成功是:无限远 概率1次的成功是:2-成功1.0 概率是: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); 
     } 
     } 
} 
+1

如果我不得不猜测,你已经有一个基于天真递归的'factorial'实现。虽然,如果你不想猜测,并想要一个真正的答案,__ – Daniel

+1

这是没有足够的代码来告诉是什么导致溢出。 – JJJ

+0

看到这段代码,我认为这个问题可能源于'factorial'(这很可能是递归实现的)。请发布整个代码以及*Exception的堆栈跟踪。 – Turing85

不,你的阶乘的实施导致堆栈溢出,不循环。

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

我也猜测你没有意识到如何容易出现溢出和效率低下幼稚析因实现。

你应该研究γ函数(γ的自然对数会更好)和记忆。

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

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

虽然这个答案很可能是正确的,但我不明白为什么人们发布答案,如果问题不明确...... – Turing85

+0

我认为问题很清楚。答案是正确的。我不明白为什么低代表巨魔认为讽刺意见比真实答案更有帮助。 – duffymo

+0

算法太天真了,即使你使用'ln'。溢出和精度损失的空间太大。仅仅因为数学使用阶乘,并不意味着你的算法*应该。 – Daniel

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

以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,并且可以只用int s为单位计算。)

注:看来,这个问题是改变在我开始输入这个内容之后,很显然,它可能无法解决最新版本的问题。