我们在学习算法基础的时候,经常遇到求n!,但是int数据类型能表示的数最大是2^32-1 ,当我们的累乘器或者累加器大于前者时,这时候我们应该用数组来表示。例如我们用a[]数组来存储n!,a[1]存储个位,a[2]存储十位,依次类推。那么问题来了,我们需要求解n!到底是几位数
设n!是m位,则可以得到下列推导过程(基于十进制数)
10^(m-1)≤n!≤10^m-1 //两边同时取对数
m-1≤㏒n!≤㏒(10^m-1)<m
∴m=㏒n! +1
接下来设置二重循环,模拟整数竖式乘法实施个数组元素的累乘,算法如下:
main()
{
int j,k,m,n,a[40000];
long carry=0,t; //carry表示进位
double s=0;
printf("请输入正整数n(n<10000):");
scanf("%d",&n);
for(k=2;k<=n;k++)
s+=log10(k);
m=(int)s+1; //对数累加,确定n!的位数m
for(k=1;k<=m;k++)
a[k]=0; //数组清零
a[1]=1;
for(k=2;k<=n;k++){
for(j=1;j<=m;j++){
t=k*a[j]+carry;
a[j]=t%10; //乘积t的个位数存于本元素
carray=t/10; //乘积t的十位数及以上存入进位数
}
}
printf("%d!=",n);
for(j=m;j>1;j--)
printf("%d",a[j]);
}
接下来再说说大整型数的乘除法,我们依旧用数组表示这个数,例如一个大整型3175432678964251234,从低位到高位一次取4位,a[1]=1234,a[2]=6425,直到a[5]=317。乘法关键算法如下:
int a[]={"1234","6425","6789","5432","317"}; //被乘数
int b=345; //乘数
int carry=0; //进位
for(int i=0;i<5;i++){
t=b*a[i]+carry;
a[i]=t%10000;
carry=t/10000;
}
除法也类似的
reminder=0;
for(int i=5;i>=1;i--){
t=(a[i]+reminder*10000)/b;
reminder=a[i]-t*b;
a[i]=t;
}