factorial of n (to prevent stack overflow)

First do it with our most familiar recursive method:

int Fun1(int n)
{
    
    
	if(n<=1)
		return 1;
	else
		return Fun1(n-1 )* n;
}

There is also the loop method:

int Fun2(int n)
{
    
    
	int sum=1;
	for(int i;i<=n;++i)
	{
    
    
		sum=sum * i;
	}
	return sum;
}

But what if we encounter the factorial of 13? 13! Out of the range of the int variable, the correct result cannot be obtained. In order to calculate the factorial of a larger number, the int type can be changed to unsigned long type.

unsigned long Fun3(unsigned long n)
{
    
    
	if(n<=1)
		return 1;
	else
		return (unsigned long)n * Fun3(n-1);
}

However, the factorial after calculating 20 will also overflow, then we have to consider the problem of stack overflow.

Consider resolving multi-digit multiplications into single-digit multiplications.
Such as 11! =39916800, if you need the factorial of 12, you need to multiply 39916800 by 12, you can use the multiplication distribution rate.
insert image description here
An array can be used to save the result of each digit of the factorial, and an array element holds a single digit.
insert image description hereThrough the carry operation, the value stored in each element in the array has only one digit. In this way, the factorial result of any number of digits can be saved, and it is no longer limited by the value range of the variable.

code show as below:

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

#define true	1
#define false	0
 
void calculat(int *fact, int n)
{
    
    
	int i;
	int num=fact[0];
	int carry=0;
 
	for(i=1; i<=num; i++)
	{
    
    
		fact[i] = fact[i]*n+carry;
		if(carry = fact[i]/10)
		{
    
    
			fact[i] = fact[i]%10;
		}
	}
	
	while(carry)
	{
    
    
		fact[i++] = carry%10;
		carry = carry/10;
	}
	fact[0] = i-1;
}
 
int Fun4(int n, int **result)
{
    
    
	double sum=1;
	int digit;
	int i;
	int	*fact;
 
	if(n<=0 || result==NULL)
	{
    
    
		return false;
	}
	for(i=1; i<=n; i++)
	{
    
    
		sum += log10(n);
	}
	
	digit = (int)sum;
	fact = (int *)malloc((digit+1)*sizeof(int));
	if(fact == NULL)
	{
    
    
		return false;
	}
	fact[0]=1;
	fact[1]=1;
	for(i=2; i< digit+1; i++)
	{
    
    
		fact[i]=0;
	}
 
	for(i=1; i<=n; i++)
	{
    
    
		calculat(fact, i);
	}
	
	*result = fact;
	return true;
}
 
void printnum(int *result)
{
    
    
	int num;
	
	if(result == NULL)
		return;
	num = result[0];
	while(num)
	{
    
    
		printf("%d",result[num]);
		num--;
	}
	printf("\n");
}
 
int main()
{
    
    
	int n;
	int *result;
 
	while(EOF != scanf("%d", &n))
	{
    
    
		if(false == Fun4(n, &result))
			return false;
		printnum(result);
		free(result);
	}
	return true;
}

Also, when providing a class method:Store each bit of data in an array
For example: Suppose we get 4! = 24, stored in reverse order in the array, that is, 42, a[1] = 4, a[2] = 2 (the array subscript starts from 1) now we need to calculate 5
! The inner for loop processes 4 and 2, that is, each bit is multiplied by 5. First a[1] = a[1]*5 + 0(h)= 20, h changes from 0 to 2, a[1] = 0; then a[2] = a[2] * 5 + 2 = 12 , h changes from 2 to 1, a[2] = 2; at this time, the execution of the inner for loop ends.
The function of the inner for loop is to update the result of the product of each of the existing digits and i.
Then execute the while loop, currently h = 1, a[3] = 1, h changes from 1 to 0, and then exit the while loop. Get a 5 when you finish processing! = 120. The number of bits of p is increased to 3 bits.
The function of the while loop is to calculate the carry after the number of digits before p is updated
For example, when p = 2, the array is 42, and then the inner for loop updates 42 to 02, and the while loop increases the carry 1, and the entire array becomes 021.
code show as below:

#define MAX 40000  
int main()  
{
    
      
    int n;  
    while(scanf("%d",&n)!=EOF&&n>=0)  
    {
    
      
        int i,j;  
        int a[MAX];      //存数运算结果  
        int p,h;           //p存储当前结果的位数,h为进位  
        a[1]=1;  
        p=1;  
        for(i=2;i<=n;i++)   //循环与2,3,4.....n相乘  
        {
    
      
            for(j=1,h=0;j<=p;j++)    //让a[]的每位与i相乘  
            {
    
      
                a[j] = a[j] * i + h ;  
                h = a[j] / 10 ;  
                a[j] = a[j] % 10 ;  
            }  
            while(h>0)         //如果h不为0  
            {
    
      
                a[j] = h % 10 ;  
                h = h / 10 ;  
                j++;  
            }  
            p = j - 1 ;            //将当前的位数赋给p  
        }  
        for(i=p;i>=2;i--)  
        {
    
      
            printf("%d",a[i]);  
        }  
        printf("%d\n",a[i]);  
    }  
    return 0;  
}  

Guess you like

Origin blog.csdn.net/Chenjiahui_LYee/article/details/102989806