階乘之計算從入門到精通-菜鳥篇

摘要:本文給出一些最簡單的計算階乘的程序,這也是許多C語方言初學者寫出的算階乘的程序。它雖然不能正確地計算出大數階乘,但它依然有許多正確的思想。讓咱們從錯誤中開始,開始一個漫長的,充滿樂趣的探索大數階乘計算之路吧…
 
程序1,一個最直接的計算階乘的程序
#include "stdio.h"
#include "stdlib.h"
 
int main(int argc, char* argv[])
{
         long i,n,p;
         printf("n=?");
         scanf("%d",&n);
         p=1;
         for (i=1;i<=n;i++)
                  p*=i;
         printf("%d!=%d/n",n,p);
         return 0;
}
 
程序2,稍微複雜了一些,使用了遞歸,一個c++初學者寫的程序
#include   <iostream.h>   
  long   int   fac(int   n);   
  void   main()   
  {   
          int   n;   
          cout<<"input   a   positive   integer:";   
          cin>>n;   
          long   fa=fac(n);   
          cout<<n<<"!   ="<<fa<<endl;   
  }   
  long   int   fac(int   n)   
  {   
          long   int   p;   
          if(n==0)   p=1;   
          else   
              p=n*fac(n-1);   
          return   p;   
  }   
  
程序點評,這兩個程序在計算12之內的數是正確,但當n>12,程序的計算結果就徹底錯誤了,單從算法上講,程序並無錯,但是這個程序到底錯在什麼地方呢?看來程序做者並無意識到,一個long型整數可以表示的範圍是頗有限的。當n>=13時,計算結果溢出,在C語言,整數相乘時發生溢出時不會產生任何異常,也不會給出任何警告。既然整數的範圍有限,那麼可否用範圍更大的數據類型來作運算呢?這個主意是不錯,那麼到底選擇那種數據類型呢?有人想到了double類型,將程序1中long型換成double類型,結果以下:
#include "stdio.h"
#include "stdlib.h"
 
int main(int argc, char* argv[])
{
   double i,n,p;
   printf("n=?");
   scanf("%lf",&n);
   p=1.0;
   for (i=1;i<=n;i++)
            p*=i;
   printf("%lf!=%.16g/n",n,p);
   return 0;
}
 
運行這個程序,將運算結果並和windows計算器對比後發現,當於在170之內時,結果在偏差範圍內是正確。但當N>=171,結果就不能正確顯示了。這是爲何呢?和程序1相似,數據發生了溢出,即運算結果超出的數據類型可以表示的範圍。看來C語言提供的數據類型不能知足計算大數階乘的須要,爲此只有兩個辦法。1.找一個能表示和處理大數的運算的類庫。2.本身實現大數的存儲和運算問題。方法1不在本文的討論的範圍內。本系列的後續文章將圍繞方法2來展開。
相關文章
相關標籤/搜索