2016-11-07 51 views
1

我有一個函數可以計算階乘和組合如下。對於一個非常大的數字計算

int faktorial(int n) 
    { 
     if((n == 0)||(n == 1)) 
     { 
      return (1); 
     } 
     else 
     { 
      return (n * faktorial(n-1)); 
     } 
    } 

    int Kombinasi(int x, int y) 
    { 
     int n = faktorial(x); 
     int k = (faktorial(x - y)) * (faktorial(y)); 
     int hasil = n/k; 
     return (hasil); 
    } 

但是在計算階乘時存在一個問題。 假設我想計算x = 1000和y = 4的組合函數。現有函數的調用階乘函數。但階乘函數不能計算它們。如何解決這個問題呢 ?。抱歉,我的英語很不好。謝謝。

+1

外表到[BigInteger的](https://msdn.microsoft.com/en-us/library/system.numerics.biginteger(V = vs.110)的.aspx)類 – Jonesopolis

+2

階乘爲1000是一個很大的數字,您需要添加數字命名空間並使用bigInteger類,使用算法計算1000的階乘可能需要很長時間,也許使用記憶或其他方法可以提高計算效率 – Overmachine

+0

如果您有興趣非遞歸階乘計算機,你可以在這裏查看我的庫的[this part](https://github.com/spearson/xofz.Core/blob/master/xofz.Core/Framework/Computation/FactorialComputer.cs)。 –

回答

1

首先,要回答你的問題 - 你可以處理更大的值(最大爲2^64 - 1)如果你使用

ulong c; 

二,一點點的幫助 - 不會幫助你的鍛鍊。即使是無符號的long也不能處理這樣大的值。但是,請注意,相反,要獲得(n選擇k),可以簡單地計算(n *(n-1)* .... *(n-k + 1))/ k! 。

+0

'unsigned long'不是C#中的一種類型。 – Kyle

+0

@凱爾老習慣難改。編輯。 – matanso

2

BigInteger作品,並在1000年相當快!

BigInteger faktorial(BigInteger n) 
{ 
    if ((n == 0) || (n == 1)) 
    { 
     return (1); 
    } 
    else 
    { 
     return (n * faktorial(n - 1)); 
    } 
} 

BigInteger Kombinasi(BigInteger x, BigInteger y) 
{ 
    BigInteger n = faktorial(x); 
    BigInteger k = (faktorial(x - y)) * (faktorial(y)); 
    BigInteger hasil = n/k; 
    return (hasil); 
} 

答:

4023872600770937735437024339230039857193748642107146325437999104299385123986290205920442084869694048004799886101971960586316668729948085589013238296699445909974245040870737599188236277271887325197795059509952761208749754624970436014182780946464962910563938874378864873371191810458257836478499770124766328898359557354325131853239584630755574091142624174743493475534286465766116677973966688202912073791438537195882498081268678383745597317461360853795345242215865932019280908782973084313928444032812315586110369768013573042161687476096758713483120254785893207671691324484262361314125087802080002616 831510273418279777047846358681701643650241536913982812648102130927612448963599287051149649754199093422215668325720808213331861168115536​​1583654698404670897560290095053761647584772842188967964624494516076535340819890138544248798495995331910172335555660213945039973628075013783761530712776192684903435262520001588853514733161170210396817592151090778801939317811419454525722386554146106289218796022383897147608850627686296714667469756291123408243920816015378088989396451826324367161676217916890977991190375403127462228998800519544441428201218736174599264295658174662830295557029902432415318161721046583203678690611726015878352075151628422554026517048330422614397428693306169089796848259012545832716822645806652676995865268227280707578139185817888965220816434834482599326604336766017699961283186078838615027946595513115655203609398818061213855860030143569452722420634463179746059468257310379008402443243846565724501440282188525247093519062092902313649327349756551395872055965422874977401141334696271542284 5862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

注意,但是,它似乎溢出上面大約8889!以上的堆棧。

1

由於看起來您真正想要做的是計算二項式係數,因此使用BigInteger的替代方法是利用階乘的一些數字屬性。因此,而不是直接計算階乘(可以是大的),可以改爲做到這一點:

long Kombinasi(long x, long y) 
{ 
    if(y == 0) return 1; 
    return (x * Kombinasi(x - 1, y - 1))/y; 
} 

您也可以使用這種算法結合BigInteger如果你需要更大的價值:

BigInteger Binomial(BigInteger n, BigInteger k) 
{ 
    if(k <= 0) return 1; 
    return (n * Binomial(n - 1, k - 1))/k; 
} 

這將比計算階乘和分裂更有效率,因爲它利用了大部分階乘項抵消的事實。它也將執行更少的乘法,特別是如果k很小。

0

正如其他成員所建議我們可以使用BitInteger作爲大數字。 我不知道它是否有用,但我想在此解釋一點。

所以讓我們說我們有一個有很大價值的signed int(int.Max)和如果你嘗試添加一些正整數值(10),它不會給你System.OverflowException。它只是給你消極的價值。所以如果你想在這種情況下引發異常。您可以使用checked關鍵字。如果表達式產生的值超出了目標類型的範圍。如果表達式包含一個或多個非常量值,則編譯器不會檢測到溢出。溢出檢查可以通過使用checked關鍵字來啓用。所以當你嘗試上面提到的東西時,它會拋出異常,你可以相應地處理它。

checked in C#