大菲波那契數的計算程序

 
大菲波那契數的計算程序
對於較大的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位來存放一個菲波那契數,但必須將相應的結果轉換爲十進制,以符合自然數的書寫習慣。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章