2013-11-23 133 views
0

程序詢問用戶翻轉硬幣的次數(n;試用次數)。計算概率C++伯努利試驗

成功被認爲是一個頭。

完美無瑕,程序會創建一個介於0和1之間的隨機數。0被視爲正面和成功。

然後,程序應該輸出獲得x個頭的期望值。例如,如果硬幣被翻轉4次,有什麼用公式

nCk * p^k * (1-p)^(n-k) 
Expected 0 heads with n flips: xxx 
Expected 1 heads with n flips: xxx 
... 
Expected n heads with n flips: xxx 

當與「較大」號這樣做下面的概率,數字出來怪異值。如果將15或20個輸入到輸入中,就會發生這種情況。我已經得到了0和負值,應該是xxx的值。

調試,我已經注意到nCk已經出來是負面的,不正確的上限值和beleive這是問題。我用這個公式我的組合:

double combo = fact(n)/fact(r)/fact(n-r); 

這裏是我的事實功能的僞代碼:

long fact(int x) 
{ 
    int e; // local counter 
    factor = 1; 
    for (e = x; e != 0; e--) 
    { 
     factor = factor * e; 
    } 
    return factor; 
} 

有什麼想法?我的猜測是我的階乘或組合函數超過最大值或什麼的。

+0

你可能會得到整數溢出。嘗試將事件函數的類型改爲double,並查看是否有更高的值被接受。 –

+0

這裏:http://stackoverflow.com/a/4701106/576911是如何計算'nCk'以最小的溢出危險,如果發生溢出,它不會默默地做。 –

回答

1

您還沒有提到如何申報factor。我認爲你正在得到整數溢出。我建議你使用雙。那是因爲你正在計算期望值和概率,所以你不應該關心精度。

嘗試改變你的事實功能。

double fact(double x) 
{ 
    int e; // local counter 
    double factor = 1; 
    for (e = x; e != 0; e--) 
    { 
     factor = factor * e; 
    } 
    return factor; 
} 

編輯: 還要計算NCK,你不必計算階乘的3倍。您可以通過以下方式簡單計算該值。

if k > n/2, k = n-k. 

     n(n-1)(n-2)...(n-k+1) 
nCk = ----------------------- 
      factorial(k) 
1

你超過了一個長的最大值。因子增長得如此之快以至於您需要正確的數字類型 - 哪種類型將取決於您需要的值。

Long是一個有符號整數,只要您通過2^31,該值將變爲負數(它使用2的補數學數學)。使用一個無符號長整數將會給你一點時間(多一點),但對於階乘來說,它可能不值得。如果你的編譯器支持long long,那麼嘗試一個「unsigned long long」。這將(通常取決於編譯器和CPU)使用的位數增加一倍。

您也可以嘗試切換使用雙。你會面臨的問題是,隨着數字的增加,你會失去準確性。 double是一個浮點數,所以你將有一個固定數目的有效數字。如果您的最終結果是一個近似值,這可能工作正常,但如果您需要確切的值,它將不起作用。

如果這些解決方案都不適合您,您可能需要求助於使用「無限精度」數學包,您應該能夠搜索這些數據包。你沒有說你是否使用C或C++;這對C++來說會更令人愉快,因爲它將提供一個類似數字的類,並使用標準算術運算符。