时间:2021-05-20
本文研究的主要内容是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。
概率统计里有一条递归公式:
这个便是题目中递归式的来源。
该递推公式来自: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 246720 10 0.25 243553830 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 10120 10 0.25 45230 15 0.25 120350 25 0.25 3204100 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.05839920043945312520, 10, 0.25 0.00992227527967770650, 25, 0.25 8.44919466990397E-5与前面的算法比对,计算结果是正确的,而且运行速度是非常之快的。
总结
以上就是本文关于Java编程二项分布的递归和非递归实现代码实例的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
本文研究的主要是Java编程实现二项分布的采样或抽样,下面是具体实现代码。如下程序为n=100,p=0.9的二项分布采样,共采样10000次packagefun
用java实现的数组创建二叉树以及递归先序遍历,递归中序遍历,递归后序遍历,非递归前序遍历,非递归中序遍历,非递归后序遍历,深度优先遍历,广度优先遍历8种遍历方
本文实例讲述了Java实现二叉树的建立、计算高度与递归输出操作。分享给大家供大家参考,具体如下:1.建立递归输出计算高度前中后三种非递归输出publicclas
数据结构二叉树的递归与非递归实例代码:#include#include#include#includeusingnamespacestd;templatestr
Java实现单链表反转,递归和非递归两种形式/***反转单链表*//***定义链表**@author16026**/classNode{intval;Noden