Java编程二项分布的递归和非递归实现代码实例

作者:ChuanjieZhu 时间:2023-08-07 09:38:04 

本文研究的主要内容是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

与前面的算法比对,计算结果是正确的,而且运行速度是非常之快的。

来源:http://blog.csdn.net/u014485485/article/details/77506844

标签:java,递归,二项分布
0
投稿

猜你喜欢

  • Java 三种进制的数值常量操作

    2021-11-14 21:39:41
  • 用c#获得当前用户的Application Data文件夹位置

    2022-02-13 10:05:22
  • Android 文件存储与SharedPreferences存储方式详解用法

    2021-07-22 20:11:54
  • android图像绘制(六)获取本地图片或拍照图片等图片资源

    2021-07-26 14:20:51
  • Spring基于注解的缓存声明深入探究

    2023-01-20 13:26:06
  • spring系列笔记之常用注解

    2022-02-21 16:15:04
  • Hibernate中的多表查询及抓取策略

    2022-02-22 18:58:28
  • 通过IDEA快速定位和排除依赖冲突问题

    2021-06-07 02:01:16
  • Android自定义TitleView标题开发实例

    2023-09-05 18:21:41
  • 基于ElasticSearch Analyzer的使用规则详解

    2023-09-28 14:41:04
  • Spring boot事件监听实现过程解析

    2022-08-29 13:46:02
  • Android实现拼图小游戏

    2023-03-01 11:25:46
  • 快速了解c# 结构体

    2022-10-19 05:38:45
  • 利用JavaMail发送HTML模板邮件

    2023-01-21 02:25:32
  • Android实现EditText图文混合插入上传功能

    2022-08-27 10:19:50
  • 一篇文章带你入门Springboot沙箱环境支付宝支付(附源码)

    2021-06-26 23:21:16
  • 探讨Android 的屏幕滚动操作不如 iPhone 流畅顺滑的原因

    2023-04-05 09:05:33
  • 利用POI生成EXCEL文件的方法实例

    2023-11-23 21:44:14
  • Java设计模式之观察者模式_动力节点Java学院整理

    2022-01-14 12:27:47
  • Android实现自定义带文字和图片Button的方法

    2021-06-20 17:13:50
  • asp之家 软件编程 m.aspxhome.com