摘要:本文給出一些最簡單的計算階乘的程序,這也是許多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來展開。