注:
對(duì)于 int 型奔害, 13楷兽! 會(huì)溢出
對(duì)于 long long 型,21华临!會(huì)溢出
思路:
1.用數(shù)組存儲(chǔ)每一位
2.將每一位都與1-n中的每一個(gè)數(shù)相乘
3.計(jì)算進(jìn)位和本位數(shù)
4.處理最后的進(jìn)位情況
#define MAX 10000
/*
//溢出情況
int result = 1;//0的時(shí)候是1
for (int i = 2; i<=n; i++) {
result *= i;
}
printf("%d\n",result); //輸出溢出的算法芯杀,方便對(duì)比
*/
int main(int argc, const char * argv[]) {
@autoreleasepool {
int n = 4;
//處理后不溢出
int a[10000];
a[1] = 1; //從a[1]開始
int p = 1; //p 表示位數(shù),剛開始只有一位a[1] 且 a[1] = 1雅潭,不能為0揭厚,0乘任何數(shù)為0
int one = 0; //one 表示進(jìn)位數(shù),剛開始進(jìn)位為0
int i,j;
int result = 1;//0的時(shí)候是1
for (i=2; i<=n; i++) {
for (j=1; j <= p; j++) {//循環(huán)a[],讓每一位都與i乘
int temp = a[j] * i + one; //temp變量表示不考慮進(jìn)位的值
one = temp / 10; //計(jì)算進(jìn)位大小
a[j] = temp % 10; //計(jì)算本位值
}
/*處理最后一位的進(jìn)位情況*/
//由于計(jì)算數(shù)組的最后一位也得考慮進(jìn)位情況扶供,所以用循環(huán)討論
//因?yàn)榭赡茏詈笠晃豢梢赃M(jìn)多位筛圆;比如 12 * 本位數(shù)8,可以進(jìn)兩位
while (one) {//當(dāng)進(jìn)位數(shù)存在時(shí)椿浓,循環(huán)————這個(gè)循環(huán)的作用就是將一個(gè)數(shù)分割太援,分割的每一位放入數(shù)組中
a[j] = one%10;
one = one/10;
j++;//表示下一位
}
p = j - 1; //由于上面while中循環(huán)有j++,所以位會(huì)多出一位,這里減去
}
for (i=p;i>=1;i--){//逆序輸出
printf("%zd",a[i]);
}
}
return 0;
}
直接看代碼比較難理解扳碍,可以舉個(gè)例子提岔,比如說我們現(xiàn)在得到了4!= 24左腔,在數(shù)組中是以倒序的方式存儲(chǔ)唧垦,即42,a[1] = 4液样,a[2] = 2(數(shù)組下標(biāo)從1開始)振亮,現(xiàn)在要計(jì)算5!鞭莽,內(nèi)層for循環(huán)對(duì)目前的兩位4和2進(jìn)行處理坊秸,即每一位都乘以5,首先a[1] = a[1]*5 + 0(h)= 20澎怒,h從0變?yōu)?褒搔,a[1] = 0;然后a[2] = a[2] * 5 + 2 = 12,h從2變?yōu)?星瘾,a[2] = 2走孽;這時(shí)內(nèi)層for循環(huán)執(zhí)行結(jié)束。
總結(jié)1:內(nèi)層for循環(huán)的作用是更新已經(jīng)存在的位數(shù)中的每一位與i的乘積的結(jié)果.
接著執(zhí)行while循環(huán)琳状,目前h = 1磕瓷,a[3] = 1,h 從1變?yōu)?,然后退出while循環(huán)念逞。處理結(jié)束就得到了5困食! = 120.p的位數(shù)增加到3.
總結(jié)2:while循環(huán)的作用是計(jì)算p更新之前的位數(shù)之后的進(jìn)位,比如說p = 2的時(shí)候翎承,數(shù)組中為42硕盹,然后內(nèi)層for循環(huán)把42更新為02,while循環(huán)增加進(jìn)位1叨咖,整個(gè)數(shù)組變?yōu)?21.
這樣就可以計(jì)算任意數(shù)的階乘瘩例,而不用擔(dān)心溢出。