日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

WV.27-大数阶乘算法7-入门篇之二

發(fā)布時(shí)間:2024/1/1 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WV.27-大数阶乘算法7-入门篇之二 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

入門(mén)篇之二

在《大數(shù)階乘之計(jì)算從入門(mén)到精通―入門(mén)篇之一》中,我們給出一個(gè)計(jì)算階乘的程序,它采用char型數(shù)組存貯大數(shù),1個(gè)元素表示1位十進(jìn)制數(shù)字,在計(jì)算時(shí),一次乘法可計(jì)算一位數(shù)字和一個(gè)整數(shù)的乘積。該算法具有簡(jiǎn)單直觀的優(yōu)點(diǎn),但缺點(diǎn)也是明顯的,速度不快,占用內(nèi)存空間也較多,本文將給出一個(gè)改后的程序,有效的克服了這些缺點(diǎn)。

學(xué)過(guò)80x86匯編的人都知道,8086/8088的CPU可對(duì)兩個(gè)16比特的數(shù)相乘,其結(jié)果為32比特,80386及其后的32位CPU可對(duì)兩個(gè)32比特的數(shù)相乘,結(jié)果為64比特(以下寫(xiě)作bit)。8086 CPU等16位CPU已完全淘汰,這是不去討論它。在32位c語(yǔ)言編譯器中,unsigned long(DWORD)型變量可以表示一個(gè)32bit的整數(shù),unsigned short(WORD)型變量可表示一個(gè)16bit的整數(shù)。兩個(gè)65535以?xún)?nèi)的數(shù)相乘,其結(jié)果完全可以存貯在一個(gè)unsigned long變量中。另外,在好多32位編譯器中,也提供了64bit的整數(shù)類(lèi)型(如在VC中,unsigned __int64可表示一個(gè)64bit的整數(shù),在GCC中,long?long可表示一個(gè)64位的整數(shù))。同理兩個(gè)40億以?xún)?nèi)的數(shù)相乘,其結(jié)果可以用一個(gè)unsigned __int64 型的變量來(lái)存儲(chǔ)。讓一個(gè)具有一次可計(jì)算兩個(gè)32bit數(shù)乘法能力的CPU一次只計(jì)算1個(gè)1位10進(jìn)制數(shù)和一個(gè)整數(shù)的乘法,實(shí)在是一種浪費(fèi)。下面我們提出兩種大數(shù)的表示法和運(yùn)算方法。

第一種方法:用WORD型數(shù)組表示大數(shù),用DWORD型變量表示兩個(gè)WORD型變量的乘積。數(shù)組的每個(gè)元素表示4位十進(jìn)制數(shù)。在運(yùn)算時(shí),從這個(gè)數(shù)的最后一個(gè)元素開(kāi)始,依次乘以當(dāng)前乘數(shù)并加上上次的進(jìn)位,其和的低4位數(shù)依然存在原位置,高幾位向前進(jìn)位。當(dāng)乘數(shù)i小于42萬(wàn)時(shí),其乘積加上進(jìn)位可以用一個(gè)DWORD型變量表示,故這個(gè)程序可以計(jì)算上到42萬(wàn)的階乘,當(dāng)計(jì)算42萬(wàn)的階乘時(shí),占用內(nèi)存空間小于1.1兆字節(jié)。至于速度,在計(jì)算1000/10000的階乘時(shí),在迅馳1.7G電腦約需0.015/0.86秒。

?

#include "stdlib.h" #include "stdio.h" #include "math.h"#define PI 3.1415926535897932384626433832795 #define RAD 10000 typedef unsigned long DWORD; typedef unsigned short WORD; //用stirling公式估算結(jié)果長(zhǎng)度,稍微算得大一點(diǎn) DWORD calcResultLen(DWORD n,DWORD rad) {double r=0.5*log(2*PI) + (n+0.5)*log(n)-n;return (DWORD)(r/log(rad)+2); }void calcFac1(DWORD n) {DWORD i,carry,prod,len;WORD *buff,*pHead,*pTail,*p; if (n==0) { printf("%d!=1",n); return; }//---計(jì)算并分配所需的存儲(chǔ)空間len=calcResultLen(n,RAD); buff=(WORD*)malloc( sizeof(WORD)*len);if (buff==NULL)return ;//以下代碼計(jì)算n!pHead=pTail=buff+len-1;for (*pTail=1,i=2;i<=n;i++){ for (carry=0,p=pTail;p>=pHead;p--){prod=(DWORD)(*p) * i +carry;*p=(WORD)(prod % RAD);carry=prod / RAD;}while (carry>0){pHead--;*pHead=(WORD)(carry % RAD);carry /= RAD;}}//顯示計(jì)算結(jié)果printf("%d!=%d",n,*pHead); for (p=pHead+1;p<=pTail;p++) printf("%04d",*p);printf("/n");free(buff);//釋放分配的內(nèi)存 } int main(int argc, char* argv[]) { DWORD n; printf("please input n:"); scanf("%d",&n); calcFac1(n); return 0; }

?

第二種方法:用DWORD型數(shù)組表示大數(shù),用unsigned __int64 表示兩個(gè)DWORD型變量的乘積。數(shù)組的每個(gè)元素表示9位十進(jìn)制數(shù)。在運(yùn)算時(shí),從這個(gè)數(shù)的最后一個(gè)元素開(kāi)始,依次乘以當(dāng)前乘數(shù)i(i=1..n)并加上上次的進(jìn)位,其和的低9位數(shù)依然存在原位置,高幾位向前進(jìn)位。從算法上講,這個(gè)程序能夠計(jì)算到40億的階乘,在實(shí)際計(jì)算過(guò)程中,僅受限于內(nèi)存的大小。至于速度,比前一個(gè)程序要慢一些,原因在于unsigned __int64的除法較慢。我們將在下一篇文章給出解決方法,下面是采用該方法計(jì)算階乘的代碼。

#define TEN9 1000000000 void calcFac2(DWORD n) {DWORD *buff,*pHead,*pTail,*p;DWORD t,i,len;UINT64 carry,prod;if (n==0){ printf("%d!=1",n); return; }//---計(jì)算并分配所需的存儲(chǔ)空間t=GetTickCount();len=calcResultLen(n,TEN9);buff=(DWORD*)malloc( sizeof(DWORD)*len);if (buff==NULL)return ;//以下代碼計(jì)算n!pHead=pTail=buff+len-1;for (*pTail=1,i=2;i<=n;i++){for (carry=0,p=pTail;p>=pHead;p--){prod=(UINT64)(*p) * (UINT64)i +carry;*p=(DWORD)(prod % TEN9);carry=prod / TEN9;}while (carry>0){pHead--;*pHead=(DWORD)(carry % TEN9);carry /= TEN9;}}t=GetTickCount()-t; //顯示計(jì)算結(jié)果 printf("It take %d ms/n",t);printf("%d!=%d",n,*pHead);for (p=pHead+1;p<=pTail;p++)printf("%09d",*p);printf("/n");free(buff);//釋放分配的內(nèi)存 }

總結(jié)

以上是生活随笔為你收集整理的WV.27-大数阶乘算法7-入门篇之二的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。