链接:https://pintia.cn/problem-sets/14/problems/742
void Print_Factorial(int N){
if(N==0){
printf("1");
return;
}
if(N<0){
printf("Invalid input");
return;
}//以上是两个例外情况
int r[3000];//用于存放结果
r[0]=1;
for (int i =1;i<3000;i++){
r[i]=-1;
}//将数组初始化为-1,方便判断边界
int t=1,i;//t代表结果的位数,一开始是1
for (int j=N;j>1;j--){
for (int k =0;k<t;k++){
r[k]*=j;//用乘数分别乘以被乘数的每一位.
}
i=1;//i存放这次循环后结果的位数
while (i){
//在循环中依次进位,并判断最终的位数t
if (r[i-1]>=10){
//如果需要进位
if (r[i]==-1){
r[i]=0;
}//因为前面把每一位都初始化成了-1,所以需要进到更高一位的时候,需要把那一位先还原成0
r[i]+=(int)(r[i-1]/10);//进位
r[i-1]%=10;
i++;//计算位数
} else if (r[i]>=0){
i++;//如果最高位不是-1,那么位数还是要加1.
} else{
// 如果最高位已经是-1(边界),那么结束循环
t=i;
i=0;//结束循环
}
}
}
// print
for (;t>0;t--){
printf("%d",r[t-1]);//依次打印
}
}
最开始的想法是用double数组拼接,这样数组长度有10就足够了(1000!大约是10^2500多),但是不好确定double的上限,而且浮点运算有一点误差,没办法接受.
然后就是现在这样数组每个元素存放一位,采用满十进一的方式计算. 这样做最大的问题是不好确认边界.
c声明数组变量的时候必须要给定固定的数组长度,因此要在一开始就把数组长度设定到大于2600,这样在下面循环的时候很难在恰当的时候退出循环.如果当前位数字为0视做边界,肯定是不恰当的.
因此我采用的是声明数组后,手动将每个元素赋值为-1这样不会出现的数字.然后需要进到新的一位的时候再重置为0.
进位的时候还有一个问题就是该如何结束循环.有两个思路,一个是用之前的位数t+现在的被乘数的位数作为循环次数,很明显,两个小于10的数字相乘肯定不会大于100.但是这样依旧不能省掉临时变量i,也不能解决边界的问题.
另一个办法是while,判断条件设为一个变量,当到达边界的时候将变量设为0以退出循环.很难说哪个更好一点.
越是在这个时候,越能理解为什么说python适合新手了.