要求:估计用以下代码计算binomial(100, 50, 0.25)的次数
  1. private static double binomial(int N, int k, double p){
  2. if(N == 0 && k == 0) return 1.0;
  3. if(N < 0 || k < 0) return 0.0;
  4. return (1.0 - p)*binomial(N-1, k, p) + p*binomial(N-1, k-1, p);
  5. }

解析:

binomial方法主要运用了二项概率的递推公式
Ex1_1_27二项分布概率计算 - 图8^{N-k}=(1-p)CN^{k-1}p^k(1-p)^{N-k-1}&space;+&space;pC{N-1}^{k-1}p^{k-1}(1-p)^{N-k}#)^{N-k}=(1-p)CN^{k-1}p^k(1-p)^{N-k-1}&space;+&space;pC{N-1}^{k-1}p^{k-1}(1-p)^{N-k})

约分即得到组合数递推公式
Ex1_1_27二项分布概率计算 - 图9

问题:

该方法一个递归就产生两个子递归,运算量非常大,如题数据会一直计算无法得到结果

改进方法:

思路:

已知二项概率公式和组合数公式
Ex1_1_27二项分布概率计算 - 图10=C_N^kp^k(1-p)^{N-k}#)

Ex1_1_27二项分布概率计算 - 图11!}#)

先计算组合数,但当N较大很大时,阶乘会超出int类型值域,所以需要每次乘一项后就约分为最简形式,可以使用求最大公约数的算法

例:

Ex1_1_27二项分布概率计算 - 图12

  1. pubilc class Ex1_1_27{
  2. //计算组合数
  3. private static double Combine(int X, int Y, int Z){
  4. if(x == 0 && Y == 0 && Z == -1){
  5. return 1;
  6. }
  7. if(x == 0) x = 1;
  8. if(Y == 0) Y = 1;
  9. if(Z == 0) Z = 1;
  10. int a = Euclid(X, Y*Z);
  11. return Combine((x*1.0/a)/(Y*Z/a));//强转或x*1.0,否则返回int
  12. }
  13. //计算概率
  14. private static double binomial(int N, int k, double p){
  15. double p1 = 1;
  16. double p2 = 1;
  17. for(int i = 1; i <= k; i++){
  18. p1 *= p;
  19. }
  20. for(int i = 1; i <= (N-k); i++){
  21. p2 *= 1-p;
  22. }
  23. double C = Combine(N, k, N-k);
  24. return C * p1 * p2;
  25. }
  26. public static void main(String[] args){
  27. System.out.println(binomial(100, 50, 0.25));
  28. //概率:6.828252801404798E-91
  29. }
  30. }