/*
* 修改後的C來源程式
* 4.剖析和最佳化下面計算階乘的C程式,要求寫出報告,必須有分析測量資料作為支援,同時應該用到課堂上所講的方法和工具。
*
* 用數組的方法解決大數、巨數的階乘結果越界的問題。具體演算法中有最樸實的乘法運算思想。
* */
/*Header 包含標頭檔*/
#include <stdio.h>
#include <stdlib.h> /* 哪個函數用到這個庫? */
#define M 1000000000L /*定義*/
#define N 60000 /* 定義數組大小:確保儲存最終運算結果的數組足夠大*/
/* Funtion函式宣告*/
int multiply(int n, unsigned int prod[N], int highest);
void print(unsigned int prod[N], int highest);
/* 主程式 */
int main(int argc, char * argv[]) {
int i, n = 0, highest = 0; /* 整數n是階乘大小。highest是位元(可是為什麼不初始化為1?highest應該小於N) */
int prod[N] = {1, 0}; /* 將結果先初始化為1。也就是說,鍵盤沒輸入參數是預設輸入參數為0,結果為1*/
if (argc > 1) n = atoi(argv[1]); /* 命令列參數:從鍵盤接收階乘大小n。*/
for (i = 2; i <= n; i++) /* 開始階乘,階乘元素從2開始依次“登場” */
highest = multiply(i, prod, highest); /* 調用階乘子程式 */
print(prod, highest);
return 0;
}
/*
*計算階乘的子程式
*
* */
int multiply(int n, /* n:要求階乘的數 */
unsigned int prod[N], /* 儲存最終運算結果的數組 */
int highest) /* 階乘結果的位元 */
{
/* tmp是階乘的任一元素與臨時結果的某位的乘積結果 */
unsigned long long tmp; /* if your compiler supports C99 */
/*unsigned __int64 tmp; */ /* if you use Visual C or Borland C */
int carrier = 0; /* 進位 */
int i;
/* 按最基本的乘法運算思想來考慮,將臨時結果的每位與階乘元素相乘 */
for (i = 0; i <= highest; i++) {
/* 相應階乘中的一項與當前所得臨時結果的某位相乘(加上進位) */
tmp = n;
tmp *= prod[i];
tmp += carrier;
/* 上面3式等價於 tmp = prod[j-1] * i + carrier; j表示此處的臨時累加器i,而i表示外層累加器i */
prod[i] = tmp % M; /* 更新臨時結果的位上資訊 */
carrier = tmp / M; /* 看是否有進位 */
}
if (carrier) /* 如果有進位 */
prod[++highest] = carrier; /* 新加一位,添加資訊。位元增1 */
carrier /= 10; /*看還能不能進位 */
return highest;
}
/*
* 輸出顯示結果
*
* */
void print(unsigned int prod[N], int highest) {
printf("%u", prod[highest]); /* ISO C99標準支援 *//* 顯示結果 */
while (highest > 0)
printf("%09u", prod[--highest]);
return;
}