问题
I need to calculate the factorial of a big number (<=1.000.000) and I need the result modulo 1000000007. I wrote the following but it generates an error when run (test.exe has stopped working). It works only for small numbers.
long long unsigned modulo(long long unsigned nr){
return nr % 1000000007;
}
long long unsigned fact(long long unsigned nr){
if(nr)return modulo(nr * fact(nr - 1));
else return 1;
}
UPDATE 1:
long long unsigned fact(long long unsigned nr){
long long unsigned r = nr;
while(--nr){
r = modulo(r * nr);
}
return r;
}
回答1:
This is because your implementation uses recursion. For small numbers it works fine, but for large numbers it overflows the stack.
This line
if(nr)return modulo(nr * fact(nr - 1));
creates nr
stack frames. Since the stack space is very limited, entering a large number causes stack overflows.
Change your implementation to use iterative calculation of the factorial to avoid the crash.
Once you are done fixing the crash, deal with the numeric overflow. Rather than computing the modulo after the factorial has been calculated, keep applying modulo at each step of the calculation.
回答2:
In worst case, you are generating 1 000 000 recursive calls, each one requiring a portion of the stack for its activation record.
Stack size is usually limited to 1MB, as soon as you use 2B per each call (actually, you will be using more than 2 bytes, often 32B or more), you will be using more than 1MB of stack, causing the segmentation fault.
回答3:
/* C code to implement factorial of large number */
#include<stdio.h>
int main(){
int a[200],index,i,j,n,tmp,counter=0;
printf("\n Enter the no : ");
scanf("%d",&n);
a[0]=1;
index=0;
//Calculation Loop
for(j=n;j>=2;j--){
tmp=0;
/* This Loop is used to multiply the numbers */
for(i=0;i<=index;i++){
tmp=(a[i]*j)+tmp; // here tmp is carry digir which should be added to next multiplied value
a[i]=tmp%10; // Extracting last digit of number
tmp=tmp/10; // Extracring carry digir
}
// This loop helps you to extract digits from last calculated carry digits
/* Supposse last carry digit is 25 then we must extract each digit( 5 & 2) and store it into array */
while(tmp>0){
a[++index]=tmp%10;
tmp=tmp/10;
}
}
//Loop to print output of calculated factorial
printf("\n The factorial of %d is : \n",n);
for(i=index;i>=0;i--)
printf("%d",a[i]);
return 0;
}
来源:https://stackoverflow.com/questions/24850272/big-number-factorial-modulo-big-prime-number