随机函数等概率返回问题

问题描述:

  1. 给定一个随机函数f,等概率返回1~5中的一个数字,
    这是唯一可以是使用的随机机制,如何实现等概率
    返回1~7中的一个数字。
  2. 给定一个随机函数f,等概率返回a~b中的一个字母,
    这是唯一可以是使用的随机机制,如何实现等概率
    返回a~d中的一个数字。

对于此类问题:二进制调整去拼。

给出一般的解法:
pic1
代码:

#include <iostream> // std::cout 
#include <stdlib.h> // rand()  srand()  RAND_MAX(32767, 0x7fff)

/** 等概率返回a~b中的一个数 
*   此函数封装好,只能用,不能修改。 
*   假设 a < b
*/
inline int f(int a, int b) {  // 7-14
	return (rand() % (b - a + 1)) + a;
} 


/** 用f等概率得到0和1 
*	a ~ b
*/
int rand01(int a, int b) {
	int ans = 0;
	bool isodd = (b - a) & 1 == 0;
	int mid = (a + b) >> 1;
	do {
		ans = f(a, b);
	} while (isodd && ans == mid);
	return isodd ? (ans < mid ? 0 : 1): (ans <= mid ? 0 : 1);
} 

/** 等概率返回 from ~ to
*   要求只能要f这个玩意儿。 
*   假设限定 from < to
*/
int g(int from, int to) {
	// 3 ~ 9
	// 0 ~ 6
	// 0 ~ range
	int range = to - from;
	int num = 1;
	// 求0~range需要多少个2进制位
	while ((1 << num) - 1 < range) {
		num++;
	}
	
	// 最终的累加和,0位上+0还是1, 1位上+0还是1, 2位上加0还是1, ... 
	int ans = 0;
	do {
		ans = 0;
		for (int i = 0; i < num; ++i) {
			ans |= (rand01(7, 14) << i);  // 这里假设给的f函数的区间为 7-14,同下面测试函数。 
		}
	} while (ans > range);
	return ans + from;
}

测试:

void test() {
	// 7 - 14,  26 - 39
	int from = 26, to = 39;
	int ans[to - from + 1];
	for (int i = 0; i < to - from + 1; ++i) {
		ans[i] = 0;
	}
	int testTime = 10000000;
	for (int i = 0; i < testTime; ++i) {
		ans[g(from, to) - from]++;
	}
	for (int i = 0; i < to - from + 1; ++i) {
		std::cout << from + i << "次数共有:" << ans[i] << "\n";
	}
}

结果: 基本等概率返回。
pic2

问题描述:
给定一个随机函数f,以p概率返回0,以1-p概率返回1,这是你唯一可以使用的随机机制,如何实现等概率返回0和1。

这个题目大同小异,0和1组合有四种,返回0概率为p,返回1概率为1-p,(一般情况p!=0.5),那么怎么等概率返回0和1呢?

p*(1-p) == (1-p)*p

这点清楚了,问题不大了。

// 提供的这个函数不可见,只能使用
int f() {
	return (rand() % 10) < 7 ? 0 : 1; // p为0.7
}

// 等概率返回0和1
int g() {
	int first = 0;
	do {
		first = f();
	} while (first == f());
	return first;
}

纸上得来终觉浅,须知此事要躬行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值