生成一组随机的概率,并按概率生成随机数的算法(c++)——基于“抛多面体试验”的算法实现

文章介绍了如何通过《概率论与数理统计》中的抛多面体试验,使用编程实现生成一组随机概率数组,利用递归快速排序对其进行排序,并按概率随机生成数字,以模拟掷骰子实验。
摘要由CSDN通过智能技术生成

一、前情提要

        其实这个方法的形成是源于《概率论与数理统计》概率定义的探究实验——抛多面体试验 — — 探索频率的统计规律性。下面以六个面为例。

二、算法实现分析

1.实验的需求分析

        1)生成一组随机的概率(总合为1)代表每一个面着地的概率,由下标代表面的编号

        2)据每一个面的概率模拟掷骰子并计数

2.代码实现分析

        1)概率生成(宏观化)

        概率在区间(0,1)又要保证总合为1,仅仅用rand()函数实现较为复杂。这里可以采用逆向思维,宏观法,先生成六个随机数,再分别将这些数除以六个数的总合,即可得每一个面的概率,储存在数组之中。

        ps:rand()在  #inclulde<stdlib.h>的库中

int main(){
	float prb[6]={0};  //创建每一面概率的函数,数组下标+1代表面的编号 	
	int i=0,sum=0;
	for(i=0;i<6;i++)	//生成随机数,并储存 
	{
		prb[i]=1+rand()%100;
		sum+=prb[i]; 
	}
    for(i=0;i<6;i++)prb[i]/=sum;//除以总数以成概率
        1.1)递归快速排序法

        为了便于第二步的计算(下一步会详细说明),这里先将数组内部概率排序。这里采用了递归快速排序法(复杂度:O(nlogn))。

void QuickSort(float a[],int low,int high) //用递归法快速排序
{
	int i=low ,j=high;
	float temp=a[low];
	
	while(i<j)
	{
		while(i<j&& temp<=a[j]) j--;    //在数组的右端扫描
		if(i<j)
		{
			a[i]=a[j];
			i++;
		}
		while (i<j&& a[i]<=temp)i++;    ///在数组的左端扫描
		if(i<j)
		{
			a[j]=a[i];
			j--;
		}
	}
	a[i]=temp;
	if(low<i)QuickSort(a,low,i-1);    //对左端子集合进行递归
	if(i<high)QuickSort(a,j+1,high);    //对右端子集合进行递归
 } 

        2)按概率随机生成数字

        将概率的大小具象化,转化成区间的长度。在由(1)中得到的总合sum的极限长度内随机选取数字,落在的区间变是所着陆的面,用指针计数即可。

void flag(int num,float *p,float prb[]){	//判断所成的面,并计数的函数 
	int SUM=0;
	for(int i=0;i<6;i++){
		if(num<(SUM+=prb[i])){
		*(p+i)+=1;
		break;
		}
	}
}
	

while (t>0){	//记录每一面的次数 
		num=1+rand()%(sum+1);
		flag(num,p,prb);
		t--;
		}

//以上仅为实现功能的代码,需要与上面的步骤联合才能一同运行

三、完整代码实现


void QuickSort(float a[],int low,int high) //用递归法快速排序
{
	int i=low ,j=high;
	float temp=a[low];
	
	while(i<j)
	{
		while(i<j&& temp<=a[j]) j--;
		if(i<j)
		{
			a[i]=a[j];
			i++;
		}
		while (i<j&& a[i]<=temp)i++;
		if(i<j)
		{
			a[j]=a[i];
			j--;
		}
	}
	a[i]=temp;
	if(low<i)QuickSort(a,low,i-1);
	if(i<high)QuickSort(a,j+1,high);
 } 
void flag(int num,float *p,float prb[]){	//判断所成的面,并计数的函数 
	int SUM=0;
	for(int i=0;i<6;i++){
		if(num<(SUM+=prb[i])){
		*(p+i)+=1;
		break;
		}
	}
}

int main(){
	float prb[6]={0};  //创建每一面概率的函数,数组下标+1代表面的编号 
	float count[6]={0};		//创建计数数组 
	float* p=count;		
	int i=0,sum=0,n,num,t;
	for(i=0;i<6;i++)	//生成随机数,并储存 
	{
		prb[i]=1+rand()%100;
		sum+=prb[i]; 
	}
	QuickSort (prb,0,5);	//获得排序后的概率表 

	scanf("%d",&n);		//输入检测次数
	t=n;
	while (t>0){	//记录每一面的次数 
		num=1+rand()%(sum+1);
		flag(num,p,prb);
		t--;
		}
	
	for(i=0;i<6;i++)printf("%d  %f  %f\n",i,(prb[i]/sum),(count[i])/n);
	} 

四、小结

在处理类似于概率的问题的时候,可以不仅仅局限于区间[0,1],而可以用宏观化、具象化的方法求得随机的概率以及按概率取值

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值