拒绝采样例题

题目链接
在这里插入图片描述

先上题代码。

int rand10() 
{
    while (true) 
    {
        int x = (rand7() - 1) * 7 + (rand7() - 1);
        if (x >= 0 && x <= 39) 
            return x % 10 + 1;
    }
}

不均匀硬币,产生等概率的问题

现有一枚不均匀的硬币 coin(),能够返回 0、1 两个值,其概率分别为 0.6、0.4。要求使用这枚硬币,产生均匀的概率分布。即编写一个函数 coin_new() 使得它返回 0、1 的概率均为 0.5。

在这里插入图片描述

不难发现,抛硬币出现0 1和1 0的概率是相等的。所以当出现0 1情况的时候就返回true,出现1 0的情况的时候就返回false。否则就继续循环

int coin_new() 
{
    while (true) 
    {
        int a = coin();
        if (coin() != a) 
        	return a;
    }
}

均匀硬币,产生不等概率问题

现有一枚均匀的硬币 coin(),能够返回 0、1 两个值,其概率均为 0.5。要求编写一个函数 coin_new(),使得它返回指定的 0、1 概率分布。

P(0) = 1/4,P(1) = 3/4

对于均匀硬币而言,连续抛两次,得到 0 0、0 1、1 0、1 1 的概率均1/4。显然,只需要连续抛两次硬币,如果得到 0 0,返回0,其他情况返回 1。

int coin_new() 
{
	int a=coin();
	int b=coin();
	if(a==0&&b==0)
		return 0;
	return 1;
}

P(0) = 1/3,P(1) = 2/3

连续抛两次硬币。如果得到 1 1,返回 0;如果得到 1 0 或 0 1,返回 1;如果得到 0 0,继续抛硬币。

int coin_new() 
{
	while(true)
	{
		int a=coin() 
		int b=coin() 
		if(a&&b)
			return 0;
		if(a||b)
			return 1;
	}
}

## P(0) = 0.3,P(1) = 0.7

1.每抛一次硬币,会得到二进制数的一位
2.连续抛 4 次硬币,可以等概率生成 [0, 15] 的每个数,记为 x
3.去掉 [10, 15],剩下 [0, 9] 的每个数依然是等概率的
4.如果 x∈[0,2],返回 0;x∈[4,9],返回 1;x ≥ 10重复上述过程

int coin_new() 
{
    while (true) 
    {
        int x = 0;
        for (int i = 0; i < 4; i++) {
            x = (x << 1) + coin();
        }
        if (x <= 2)
         return 0;
        if (x <= 9)
         return 1;
    }
}

Rand7 生成 Rand10

将 Rand7() 视作一个 7 进制位的生成器。由于 Rand7() 的结果范围是 [1, 7],故我们取 Rand7() - 1 作为对应的 7 进制位。每执行 k次 Rand7(),将得到一个 k位的 7 进制整数,在 [0, 7^k-1][范围内均匀分布。

int rand10() 
{
    while (true) 
    {
        int x = (rand7() - 1) * 7 + (rand7() - 1);
        if (x >= 0 && x <= 39) 
            return x % 10 + 1;
    }
}

优化

这样我们依然有[40,48]的数字没有用上。我们继续使用rand7()生成7进制。则到x>=40时。(x%40)*7+rand7()可以生成[1,63]的等概率的随机数y。我们可以用生成的随机数y,当y位于[1,60]时%10,可以生成等概率的[1,10].
此时,没有使用的还有61,62,63。计算 (x%61) * 7 + Rand7(),相当Rand2() * 7 + Rand7(),可以得到 [1, 21] 范围的均匀随机整数,这时再作取余运算,只有 1 个无用数字(21):

int rand10() 
{
    while (true) 
    {
        int x = (rand7() - 1) * 7 + (rand7() - 1);
        if (x >= 1 && x <= 40) 
        	return x % 10 + 1;
        x = (x % 40) * 7 + rand7();
        if (x <= 60) 
        	return x % 10 + 1;
        x = (x%61) * 7 + 7;
        if (x <= 20) 
        	return x % 10 + 1;
    }
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

影中人lx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值