Java:避免阶乘溢出

时间:2014-05-01 19:49:28

标签: java overflow factorial

我应该优化以下代码,以便计算中心二项式系数,直到整数的最大值(最多n = 16)。

public static int factorial(int n)
{
    int result= 1;

    for(int i = 2; i <= n; i++) result *= i;

    return result;
}

public static int centralbinom(int n)
{
    return factorial(2*n) / (factorial(n) * factorial(n));
}

当然,每增加一个n&gt; 6。 我如何分解&#39;阶乘函数,因此不必处理大数,如2n = 2 * 16 = 32?

或者有更好的方法来计算中心二项式系数吗?

4 个答案:

答案 0 :(得分:3)

除了使用可能会减少计算的BigIntegers之外,您还可以执行以下几项优化,在大多数情况下,您可能会在程序中出现溢出。

  1. 因为你需要至少两次阶乘(n)。计算一次并将其存储在变量中。
  2. 因子(2 * n)中包含factorial(n)。既然你已经计算了阶乘(n),你需要做的就是计算到阶乘(2n ...... n),然后将阶乘(n)乘以它。这是一种如何做到这一点的方法。

    //Pseudocode
    
    //find factorial of n given I know already till k
    
    int findFactorial(n, k) {
      int result = 1
      for i n to 1
    
        if(i==k) 
           break;
    
        result = result * n;
      return result
    }
    
    //factorial(2*n) = facorial(n, k) * factorial(k)
    
  3. 这会大大减少你的计算量,如果你希望你的程序没有溢出,你就可以使用BigIntegers了。

答案 1 :(得分:2)

如果你需要一个大数的阶乘,你必须使用BigInteger类来计算结果:

public static BigInteger factorial(int n) {
    BigInteger result = BigInteger.ONE;

    for (int i = 2; i <= n; ++i) {
        result = result.multiply(BigInteger.valueOf(i));
    }

    return result;
}

答案 2 :(得分:0)

如果中心二项式系数17大于整数最大值,并且您只需要计算17个数字,那么显而易见的解决方案是查找表。创建一个17元素的数组,其中包含n = 0到16的中心二项式系数。我认为你会发现这个解决方案非常有效。

您可以在此处找到它们的列表。 http://oeis.org/A000984

答案 3 :(得分:0)

只需通过gamma压缩你的阶乘。 将gamma设置为10就足够了

public static double factorial(int n, double gamma)
{
    double result= 1;
    double gammaInv = 1.0/gamma;
    for(int i = 2; i <= n; i++) result *= pow(i,gammaInv);

    return result;
}

public static int centralbinom(int n, double gamma)
{
    return pow(factorial(2*n,gamma) / 
        (factorial(n,gamma) * factorial(n),gamma),
        gamma);
}