天天看點

大數問題:求N的階乘

最近看了一些關于求大數N的階乘的方法,有點心得,特書寫出來,共同交流。題目:輸入一個正整數N,輸出N的階乘。N的範圍是0-1000.1000的階乘位數有兩三千位,顯然是很驚人的大資料。最開始,想到的是用字元串來表示,然後實作出字元串的加法和乘法。這樣用char[5000]足可以表示結果,占用記憶體也隻是40KB而已。但要實作字元串的乘法,比較繁瑣耗時,是以有點不太可取。後來看到網上有很多解法,其中比較常見的是用數組來表示結果,比如用int a[10000]來存放結果,輸出時依次按位輸出即可,但因每位上隻表示0-9,大大浪費了int型表示的空間(2^32=4*10^9。是以可考慮大進制數表示,比如10000.(之是以選擇10000,是因為考慮到兩個小于10000的數相乘不會超過int型表示的最大範圍)。這樣做,會大大節省記憶體,求1000的階乘,隻需要記憶體int a[500],2KB即可。

代碼如下:

#include "stdafx.h"

#include <iostream>

#include <stdio.h>

#include <Windows.h>

using namespace std; 

void PrintNum(int num)//對于不夠四位的要補零

{

if (num>999)

    {

  printf("%d",num);

    }

 else

 {

  if (num==0)

  {

   for(int i=0;i<4;i++)

   {

    printf("%d",0);

   }

  }

  else

  {

   int iCount=0;

   int curentNum=num;

   while(curentNum)

   {

    iCount++;

    curentNum/=10;

   }

   for(int i=0;i<4-iCount;i++)

   {

    printf("%d",0);

   }

   printf("%d",num);

  }  

 }

}

int _tmain(int argc, _TCHAR* argv[])

{

 //用10000進制進行表示

 int a[500];

 int n;

 int i,j;

 LONG64 itime=GetTickCount();

 while(scanf("%d",&n)!=EOF)

 {

  if(!n)

  {

   printf("1\n");

   continue;

  }

  memset(a,0,sizeof(a));

  int len=1;

  a[1]=1;

  for(i=1;i<=n;i++)

  {

   for(j=1;j<=len;j++)

   {

    a[j]*=i;

   }

   for(j=1;j<=len;j++)

   {

    if (a[j]>9999)

    {

     if (j==len)

     {

      len++;

     }

     a[j+1]+=a[j]/10000;

     a[j]%=10000;

    }

   }

 }

 printf("%d",a[len]);

 for(i=len-1;i>=1;i--)

 {

   PrintNum(a[i]);//進行補零輸出

 }

 cout<<endl;

 int iRuntime=GetTickCount()-itime;

 cout<<iRuntime<<endl;

}

 return 0;

}

運作結果圖:最後一行是運作時間

大數問題:求N的階乘

繼續閱讀