大菲波那契數的計算程序
大菲波那契數的計算程序
對於較大的n,由於f[n]已超過計算機字長所能表示的範圍,如何利用計算機來精確地生成的f[n]值呢?例如,當n=100時,f[1000]的值大大超過了無符號長整數所能表示的範圍,很多對程序設計已有相當多經驗的程序員對此不知所措。
事實上這一問題的解決非常簡單,設想讓我們用紙和筆來計算f[100],所要做的無非是反覆進行多位數的加法,如果我們將每位數用數組的一個單元來表示,一個菲波那契數用一個數組表示,只要設計一個多位數的加法程序,相應地,將前面計算小菲波那契數的程序加以改造,問題不就解決了嗎?!
爲此,定義一個多位數的結構:
#define RADIX 10
typedef struct tagMPInt
{
int length;
int bit[MAXBITS];
} MPInt;
實現多位數加法的函數爲:
void MPIntAdd(MPInt *z, MPInt *x, MPInt *y)
{
int i, carry;
long t;
i = 0;
carry = 0;
while (i < x->length && i < y->length)
{
t = (long)x->bit[i] + y->bit[i] + carry;
z->bit[i] = (int)(t % RADIX);
carry = (int)(t / RADIX);
i++;
}
if (x->length > y->length)
while (i < x->length)
{
t = (long)x->bit[i] + carry;
z->bit[i] = (int)(t % RADIX);
carry = (int)(t / RADIX);
i++;
}
if (x->length < y->length)
while (i < y->length)
{
t = (long)y->bit[i] + carry;
z->bit[i] = (int)(t % RADIX);
carry = (int)(t / RADIX);
i++;
}
if (carry != 0)
{
z->bit[i] = carry;
i++;
}
z->length = i;
}
大菲波那契數的計算程序爲:
// File: FibBig.C
#include "MPArth.h"
void FibTable()
{
MPInt F0, F1;
MPInt f0, f1, f;
int i, n;
FILE *fp = fopen("fib.dat", "w");
n = 250;
MPIntSetValue1(&F0, 1); // Set fib[0]
fprintf(fp, "fib[ 0]=1/n");
MPIntSetValue1(&F1, 1); // Set fib[1]
fprintf(fp, "fib[ 1]=1/n");
f0 = &F0;
f1 = &F1;
for (i = 2; i <= n; i++)
{
MPIntAdd(f0, f0, f1);
// Swap f0, f1
f = f0;
f0 = f1;
f1 = f;
fprintf(fp, "fib[%3d]=", i);
MPIntPrint(f1);
}
fclose(fp);
}
程序MPAdd有很大的改進餘地,該程序的設計完全模擬手工演算過程,用一個字長存放一個十進制位,沒有充分利用計算機的空間資源和計算能力。容易看出,若將基數RADIX加大,可以加快問題求解的速度。例如,將RADIX的宏定義改爲
#define RADIX 10000
不必修改程序,計算速度將加快4倍。當然,RADIX=256時,可以充分地發揮計算機的時空效能,這時已不需要1000位來存放一個菲波那契數,但必須將相應的結果轉換爲十進制,以符合自然數的書寫習慣。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.