91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java編程二項分布的遞歸和非遞歸實現代碼實例

發布時間:2020-08-31 02:15:12 來源:腳本之家 閱讀:280 作者:ChuanjieZhu 欄目:編程語言

本文研究的主要內容是Java編程二項分布的遞歸和非遞歸實現,具體如下。

問題來源:

算法第四版 第1.1節 習題27:return (1.0 - p) * binomial(N - 1, k, p) + p * binomial(N - 1, k - 1, p);
計算遞歸調用次數,這里的遞歸式是怎么來的?

二項分布:

定義:n個獨立的是/非試驗中成功次數k的離散概率分布,每次實驗成功的概率為p,記作B(n,p,k)。

概率公式:P(ξ=K)= C(n,k) * p^k * (1-p)^(n-k)

其中C(n, k) = (n-k) !/(k! * (n-k)!),記作ξ~B(n,p),期望:Eξ=np,方差:Dξ=npq,其中q=1-p。

概率統計里有一條遞歸公式:

Java編程二項分布的遞歸和非遞歸實現代碼實例

這個便是題目中遞歸式的來源。

該遞推公式來自:C(n,k)=C(n-1,k)+C(n-1,k-1)。實際場景是從n個人選k個,有多少種組合?將著n個人按1~n的順序排好,假設第k個人沒被選中,則需要從剩下的n-1個人中選k個;第k個選中了,則需要從剩下的n-1個人中選k-1個。

書中二項分布的遞歸實現:

public static double binomial(int N, int k, double p) { 
    COUNT++; //記錄遞歸調用次數 
    if (N == 0 && k == 0) { 
      return 1.0; 
    } 
    if (N < 0 || k < 0) { 
      return 0.0; 
    } 
    return (1.0 - p) * binomial(N - 1, k, p) + p * binomial(N - 1, k - 1, p); 
  } 

實驗結果:

n   k   p   調用次數
10  5  0.25  2467
20  10  0.25  2435538
30  15  0.25  2440764535 

由結果可以看出來這個遞歸方法需要調用的次數呈幾何災難,n到50就算不下去了。

改進的二項分布遞歸實現:

private static long COUNT = 0; 
  private static double[][] M; 
   
  private static double binomial(int N, int k, double p) { 
    COUNT++; 
    if (N == 0 && k == 0) { 
      return 1.0; 
    } 
    if (N < 0 || k < 0) { 
      return 0.0; 
    } 
    if (M[N][k] == -1) { //將計算結果存起來,已經計算過的直接拿過來用,無需再遞歸計算 
      M[N][k] = (1.0 - p) * binomial(N - 1, k, p) + p * binomial(N - 1, k - 1, p); 
    } 
    return M[N][k]; 
  } 
 
  public static double Binomial(int N, int k, double p) { 
    M = new double[N + 1][k + 1]; 
    for (int i = 0; i <= N; i++) { 
      for (int j = 0; j <= k; j++) { 
        M[i][j] = -1; 
      } 
    } 
    return binomial(N, k, p); 
  } 

實驗結果:

n    k   p   調用次數
10    5  0.25  101
20   10  0.25  452
30   15  0.25  1203
50   25  0.25  3204
100  50  0.25  5205

由實驗結果可以看出調用次數大幅減小,算法可以使用。

二項分布的非遞歸實現:

事實上,不利用遞歸,直接計算組合數和階乘,反而速度更快。

//計算組合數 
public static double combination(double N, double k) 
{ 
  double min = k; 
  double max = N-k; 
  double t = 0; 
 
  double NN=1; 
  double kk=1; 
   
  if(min>max){ 
    t=min; 
    min = max; 
    max=t; 
  } 
   
  while(N>max){//分母中較大的那部分階乘約分不用計算 
    NN=NN*N; 
    N--; 
  } 
   
  while(min>0){//計算較小那部分的階乘 
    kk=kk*min; 
    min--; 
  } 
   
  return NN/kk; 
} 
 
//計算二項分布值 
public static double binomial(int N,int k,double p) 
{ 
  double a=1; 
  double b=1; 
   
  double c =combination(N,k); 
   
  while((N-k)>0){ //計算(1-p)的(N-k)次方     
    a=a*(1-p); 
    N--; 
  } 
   
  while(k>0){ //計算p的k次方   
    b=b*p; 
    k--; 
  } 
   
  return c*a*b; 
} 

實驗結果:

n   k  p      二項分布值
10,  5, 0.25  0.058399200439453125
20, 10, 0.25 0.009922275279677706
50, 25, 0.25  8.44919466990397E-5  

與前面的算法比對,計算結果是正確的,而且運行速度是非常之快的。

總結

以上就是本文關于Java編程二項分布的遞歸和非遞歸實現代碼實例的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

区。| 双桥区| 南岸区| 斗六市| 山丹县| 九龙坡区| 葫芦岛市| 星座| 留坝县| 浦县| 洛扎县| 银川市| 监利县| 白河县| 郓城县| 轮台县| 望奎县| 贵南县| 迁安市| 永和县| 响水县| 牙克石市| 越西县| 灌南县| 静安区| 高淳县| 河南省| 南汇区| 福州市| 宁夏| 静乐县| 彰化县| 金川县| 晋江市| 镇坪县| 阳信县| 东乌珠穆沁旗| 嘉黎县| 余江县| 双江| 封丘县|