如何计算C中的大nPr?

时间:2012-10-21 16:46:49

标签: c

我已经编写了一个函数来计算C中两个数的nPr,你能不能帮我调整它来处理大数?

我需要能够计算高达1x10 ^ 12的值 - 我尝试过很多不同的数据类型,而且非常困难!

#include<stdio.h>
    #include<math.h>

int main()
    {
        long int n=49,k=6;
            printf("%li nPr %li = %li\n\n",n,k,nPr(n,k));

        return 0;

    }      

long nPr(long int n, long int k);
     long nPr(long int n, long int k){

        if (n < 0 ){
            printf("\nERROR - n is less than 0\n\n");
            return -1;
        }

        if (k > n ){
            printf("\nERROR - k is greater than n\n\n");
            return -1;
        }

        else {
            long int i,result = 1,c=n+1-k;

            for(i=c; i<=n; i++)
            {
                result = result * i;
            }
            return result;
        }
     }

由于

Ĵ

更新:这些是没有回复的排列,

我也试过

long long nPr(long long int n, long long int k);
long long nPr(long long int n, long long int k){

    if (n < 0 ){
        printf("\nERROR - n is less than 0\n\n");
        return -1;
    }

    if (k > n ){
        printf("\nERROR - k is greater than n\n\n");
        return -1;
    }

    else {
        long long int i,result = 1,c=n+1-k;

        for(i=c; i<=n; i++)
        {
            result = result * i;
        }
        return result;
    }
 }
然而,它似乎没有任何区别

2 个答案:

答案 0 :(得分:4)

您可能希望使用bignums进行计算,也许使用GMP库。如果您切换到C ++,即使对于bignums,也可以使用the C++ class interface to GMP使用熟悉的a+b表示法。如果你保持纯C,你需要仔细使用特定的例程,例如mpz_add添加。

BTW,某些语言(例如Common Lisp)本身支持bignums(无需修改处理普通数字的源代码)。您可能想尝试使用SBCL(至少在Linux上)。

当然,bignum算术(一个非常复杂的主题)比本机算术慢。

C本身不支持Bignums,你需要使用一个库(或者自己实现它,这是没有意义的:bignums的好算法很难理解和实现,所以最好使用现有的库)。

PS。 long long不会真正有用,因为它仍然是64位。一些GCC编译器和目标处理器可能支持__int128,即128位整数,但你确实需要bignums。

答案 1 :(得分:1)

分割时不需要全面评估阶乘,这样可以降低整数溢出的风险(同时提高效率):

long factorialDivision(int topFactorial, int divisorFactorial)
{
    long result = 1;
    int i;
    for (i = topFactorial; i > divisorFactorial; i--)
        result *= i;
    return result;
}

long factorial(int i)
{
    if (i <= 1)
        return 1;
    return i * factorial(i - 1);
}

long nPr(int n, int r)
{
    // naive: return factorial(n) / factorial(n - r);
    return factorialDivision(n, n - r);
}

long nCr(int n, int r)
{
    // naive: return factorial(n) / factorial(r) * factorial(n - r);
    return nPr(n, r) / factorial(r);
}