n的階乘會溢出?解決超大數字階乘溢出問題。

在我們面試時通常會遇到階乘的問題,當然最簡單的就是運用遞歸,循環所求的階乘數:

不多數,直接上代碼:

/**  
 * 實現10的階乘 
 * @author fx * */  
public class JieCheng {  
  public static void main(String[] args) {    
    System.out.println(getFactorialSum(10)+"");//通過循環實現階乘   
    int sum=1,n=10;   
    for(int i=1;i<=n;i++){    
      sum=sum*i;   
    }  
    System.out.println(sum);  
  }  
  //通過遞歸實現階乘  
  private static int getFactorialSum(int n){   
    if(n==1||n==0){     
      return 1;    
    }else{     
      return getFactorialSum(n-1)*n;   
    }  
  }  
}
當我們到13的階乘時,則會計算不出,這時我們可以把int類型轉換成long類型,但是,當計算到很大的數字時,也會運行異常。
這時,我們需要轉換一下思維。這裏運用採用 “數組進位” 算法。在超越計算機變量取值範圍的情況下,將多位數相乘轉化爲一位數相乘。如11!=39916800,若需求12的階乘,則需要將39916800與12相乘,可利用乘法分配率。乘法豎式如下圖所示:


理論上講,只要計算機內存空間允許就可以保存任意多位的階乘結果,不再受變量的取值範圍的限制,只受到操作系統的尋址能力和計算機內存的限制。如果要求的階乘數字很大則可以將數組定義爲 long 類型,以避免在計算單位數的乘積時出現溢出的情況。不多說了,上代碼:
package demo;

/**
 * Created by fx.
 */

    public class BigInteger
    {
        /**
         * 計算進位
         * @param bit	 數組
         * @param pos 用於判斷是否是數組的最高位
         */
        private void carry(int[] bit, int pos)
        {
            int i ,carray = 0;
            for(i = 0 ; i<= pos ;i++)//從0到pos逐位檢查是否需要進位
            {
                bit[i] += carray;//累加進位
                if(bit[i] <= 9)	 //小於9不進位
                {
                    carray = 0;
                }
                else if(bit[i] >9 && i 9 && i >= pos)//大於9,且是最高位
                {
                    while(bit[i] > 9)//循環向前進位
                    {
                        carray = bit[i]/10;//計算進位值
                        bit[i] = bit[i] % 10;//當前的第一位數
                        i ++ ;
                        bit[i] = carray;//在下一位保存進位值
                    }
                }
            }
        }

        /**
         * 大整數階乘
         * @param bigInteger 所計算的大整數
         */
        private  void bigFactorial(int bigInteger)
        {
            int pos =0;//
            int digit;//數據長度
            int a , b ;
            int m = 0 ;//統計輸出位數
            int n  = 0 ;//統計輸出行數
            double sum = 0;//階乘位數
            for(a = 1 ; a <= bigInteger ; a ++)//計算階乘位數
            {
                sum += Math.log10(a);
            }
            digit = (int)sum + 1;//數據長度

            int[] fact = new int[digit];//初始化一個數組
            fact[0]  = 1;//設個位爲 1

            for(a = 2 ; a <= bigInteger ; a++ )//將2^bigInteger逐個與原來的積相乘
            {
                for(b = digit-1 ; b >= 0 ; b--)//查找最高位{}
                {
                    if( fact[b]  !=  0 )
                    {
                        pos = b ;//記錄最高位
                        break;
                    }
                }

                for(b = 0; b <= pos ; b++)
                {
                    fact[b] *= a ;//每一位與i乘
                }
                carry(fact,pos);
            }

            for(b = digit-1 ; b >= 0 ; b --)
            {
                if(fact[b] != 0)
                {
                    pos = b ;//記錄最高位
                    break;
                }
            }
            System.out.println(bigInteger +"階乘結果爲:");
            for(a = pos ; a >= 0 ; a --)//輸出計算結果
            {
                System.out.print(fact[a]);
                m++;
                if(m % 5 == 0)
                {
                    System.out.print(" ");
                }
                if(40 == m )
                {
                    System.out.println("");
                    m = 0 ;
                    n ++;
                    if(10 == n )
                    {
                        System.out.print("\n");
                        n = 0;
                    }
                }
            }
            System.out.println("\n"+"階乘共有: "+(pos+1)+" 位");

        }

        public void doBigFactorial(int bigInteger)
        {
            int timeBegin=(int) System.currentTimeMillis();
            this.bigFactorial(bigInteger);
            int timeFinishi=(int) System.currentTimeMillis();
            int time = timeFinishi-timeBegin;
            System.out.println("計算耗時: " + time +"毫秒" );
        }

        public static void main(String[] args)
        {
            BigInteger bi = new BigInteger();
            bi.doBigFactorial(100000);
        }
    }
此處計算的100000的階乘(當然可以修改成其他數字)。
結果如下:




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章