1. 程式人生 > >演算法實現求n的階乘(防止溢位)

演算法實現求n的階乘(防止溢位)

求大整數n階乘,在找工作筆試和麵試的過程中,不止一次遇到這個問題,用一個for迴圈迭代出的結果肯定是不行的,即直接用int,預設是32位,它能表示的最大值為2,147,483,647,但是12的階乘為479,001,600,13的階乘為6,227,020,800,所以當n為13的時候已經溢位了。所以當n為更大的值時,需要採用巧妙的方法來防止溢位。

我們可以用陣列的方式來儲存每一位資料。

具體程式碼如下:

#include <iostream>  
#include <cstdio>  
#define MAX 40000  
using namespace std;  
  
int main(void)  
{  
    int n;  
    while(scanf("%d",&n)!=EOF&&n>=0)  
    {  
        int i,j;  
        int a[MAX];      //存數運算結果  
        int p,h;           //p儲存當前結果的位數,h為進位  
        a[1]=1;  
        p=1;  
        for(i=2;i<=n;i++)   //迴圈與2,3,4.....n相乘  
        {  
            for(j=1,h=0;j<=p;j++)    //讓a[]的每位與i相乘  
            {  
                a[j] = a[j] * i + h ;  
                h = a[j] / 10 ;  
                a[j] = a[j] % 10 ;  
            }  
            while(h>0)         //如果h不為0  
            {  
                a[j] = h % 10 ;  
                h = h / 10 ;  
                j++;  
            }  
            p = j - 1 ;            //將當前的位數賦給p  
        }  
        for(i=p;i>=2;i--)  
        {  
            printf("%d",a[i]);  
        }  
        printf("%d\n",a[i]);  
    }  
    return 0;  
}  
直接看程式碼比較難理解,可以舉個例子,比如說我們現在得到了4!= 24,在陣列中是以倒序的方式儲存,即42,a[1] =  4,a[2] = 2(陣列下標從1開始),現在要計算5!,內層for迴圈對目前的兩位4和2進行處理,即每一位都乘以5,首先a[1] = a[1]*5 + 0(h)= 20,h從0變為2,a[1] = 0;然後a[2] = a[2] * 5 + 2 = 12,h從2變為1,a[2] = 2;這時內層for迴圈執行結束。

總結1:內層for迴圈的作用是更新已經存在的位數中的每一位與i的乘積的結果.

接著執行while迴圈,目前h = 1,a[3] = 1,h 從1變為0,然後退出while迴圈。處理結束就得到了5! = 120.p的位數增加到3.

總結2:while迴圈的作用是計算p更新之前的位數之後的進位,比如說p = 2的時候,陣列中為42,然後內層for迴圈把42更新為02,while迴圈增加進位1,整個陣列變為021.

這樣就可以計算任意數的階乘,而不用擔心溢位,自己的一點總結,積累知識,溫故而知新,為自己加油!