c++概率

本文探讨如何使用一个返回0-6随机数的函数构造出0-9随机数的函数,保证概率均等。此外,还讨论了如何设计随机数生成器以实现概率相等的01序列,以及解决实数随机变量在特定区间内分布的问题。此外,还介绍了水塘抽样(Reservoir Sampling)方法和随机排列函数shuffle的应用。
摘要由CSDN通过智能技术生成

算法题

用返回0-6随机数的函数构造返回0-9随机数的函数

问题:给定一个返回06的随机自然数的函数,记为rand6(),则如何用rand6()函数构造返回09随机自然数的函数rand9()?

对于此问题,首先最容易想到的rand6() + 3、rand6() * 1.5、rand6()*2 - 4 等很明显都是错误的(rand6() + 3将返回的是3~9之间的随机数;rand6() * 1.5对于在返回int型的随机数时某些随机数不能产生;rand6()*2 - 4会产生负数)。

如果我们考虑相加,即rand6()+rand6(),这样产生的随机数的范围是012,所以我们在产生1012之间的随机数时不保留而重新产生一个新的随机数。这样做似乎是正确的,然而我们却忽略了一点:每个随机数产生的概率相等,即等概率。产生0只有一种可能(两次产生的随机数都为0),产生1却有两种可能(两次产生的随机数分别为0、1或1、0),……

再考虑相乘,即rand6()*rand6(),这样产生的随机数的范围是036,在产生3036之间的随机数时不保留而重新产生一个新的随机数,最后除以3返回。这样做同样不满足等概率,两次产生的随机数只要有一个为0返回的结果即为0,而只有两次产生的随机数都为1时返回的结果才为1,……
因此简单的直接相加相乘都是错的。

我们可以想,第一个rand6()产生一个06范围的随机数a,第二个rand6()产生一个06范围的随机数b,如果(a, b)这一对数可以确定一个唯一的数,从而可以产生的49个数(a和b都有7种可能,则(a, b)确定的数就有7*7=49种可能)都是等概率的。这就相当于有一个二维坐标系,X轴和Y轴上都可以取0~6的数,对于取x=a,y=b可以确定一个唯一的点(a, b)。

想到这个就是我们的关键,接下来就是想办法构造函数使得产生的每个数都是唯一的。我们不难想到把第一个rand6()产生的随机数a放在个位上,而把第二个rand6()产生的随机数b放在十位上,所有可能为:0006,1016,2026,3036,4046,5056,6066。很容易看出这些就是7进制数,所以我们用rand6()*7+rand6()就能生成049范围的随机数,而且每个数产生的概率相等,都是1/49。产生4049之间的随机数时不保留而重新产生一个新的随机数,这样产生039之间的数也是等概率的,仍然都是1/49,对于产生的数我们记为r(0<= r <=39),则个位数上的数就是想要的数。
具体的函数构造的C++代码如下:

int rand9()               // 用rand6()编写随机产生0~9之间的数
{
   
    int a, b, r;
    do{
   
        a = rand6();    // 随机产生0~6之间的数
        b = rand6();
        r = a * 7 + b;
    } while (r >= 40);
 
    return r / 10 +1;
}

如果进行测试,可写出完整代码如下:

#include <iostream>
#include <ctime>
using namespace std;
 
// 随机产生0~6之间的数
int rand6()
{
   
	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值