當計算超過20以上的階乘時,階乘的結果值往往會很大。一個很小的數字的階乘結果就可能超過目前個人計算機的整數範圍。如果需求很大的階乘,比如1000以上完全無法用簡單的遞歸方式去解決。在網上我看到很多用C、C++和C#寫的一些關於大整數階乘的算法,其中不乏經典但也有很多粗糙的文章。數組越界,一眼就可以看出程序本身無法運行。轉載他人文章的時候,代碼倒是仔細看看啊。唉,粗糙。過年了,在家閒來蛋疼,仔細分析分析,用Java實現了一個程序計算超大整數階乘。思想取自網上,由我個人優化和改進。
這個方法採用“數組進位”算法。在超越計算機變量取值範圍的情況下,將多位數相乘轉化為一位數相乘。如11! =39916800,若需求12的階乘,則需要將39916800與12相乘,可利用乘法分配率。乘法豎式如下圖所示:
使用一個數組來保存階乘每一位的結果,一個數組元素保存一位數。例如:將11的階乘的結果399
16800保存到數組的8個元素中,要計算12的階乘就用每個數組元素中的值去乘以12,並將結果保存到原來的數組元素中。接下來去判斷每個數組元素是否需要進位,通過進位操作使數組中的每個元素保存的數都只有一位數,示意圖如下:
理論上講,只要計算機內存空間允許就可以保存任意多位的階乘結果,不再受變量的取值範圍的限制,只受到操作系統的尋址能力和計算機內存的限制。友情提示:如果要求的階乘數字很大則可以將數組定義為long類型,以避免在計算單位數的乘積時出現溢出的情況。
實現代碼如下:
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<pos)//大於9,但不是最高位{carray = bit[i]/10;//保存進位值bit[i] = bit[i]%10;//得到該位的一位數} else if(bit[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;//設個位為1for (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);}}計算10,0000的階乘,顯示結果如下:
這樣的結果,控制台顯然已經無法保存內容了。 10萬的階乘有45萬位之多,這就相當於一本有45萬字的小說一樣。對比1000的階乘結果如下:
控制台可以完整顯示。
總結
以上就是本文關於Java版超大整數階乘算法代碼詳解-10,0000級的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站:
《 java中冪指數值的運算代碼解析》
《 Java編程實現對十六進製字符串異或運算代碼示例》
《 Java編程實現基於用戶的協同過濾推薦算法代碼示例》
如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!