利用等概率Rand5产生等概率Rand3

转自http://outofmemory.cn/wr/?u=http%3A%2F%2Fwww.gocalf.com%2Fblog%2Funbalanced-coin.html

利用等概率Rand5产生等概率Rand3

问题本身很明确,但不知道起个什么题目好,姑且先这么说吧。

问题描述:现在有一个叫做Rand5的函数,可以生成等概率的[0, 5)范围内的随机整数,要求利用此函数写一个Rand3函数(除此之外,不能再使用任何能产生随机数的函数或数据源),生成等概率的[0, 3)范围内的随机整数。

我第一次遇到这个问题的时候,着实犯了一回傻,自以为是地证明了这个题目是无解的。其实从概率的角度来看,题目的要求就是,利用一个1/5的概率源,通过某种方式产生出1/3的概率输出。我们都知道,概率运算法则有加法和乘法,而在我的记忆中,算法是“在有限步骤内求解某一问题所使用的一组定义明确的规则”,算法的一个重要特征就是有穷性,即一个算法必须保证执行有限步之后结束。那么有限多个1/5通过加法和乘法是不可能的到1/3这个数值的,因为加法和乘法都不会给分母带来新的因子,那么分母中的3根本就不可能出现。

然而我忽略了这样一个式子:

∑i=0∞(25)i=11−25=53

基于这个想法,我们来看看这个算法是什么样子的:

1
2
3
4
5

def Rand3():
    x = -1
    while not 0 <= x < 3:
        x = Rand5()
    return x

1
2
3
4
5
6
7
8
9

int Rand3()
{
    int x;
    do
    {
        x = Rand5();
    } while (x >= 3);
    return x;
}

算法很简单,x是我们最终要输出的数字,只要它不在[0, 3)范围内,就不断地调用Rand5来更新它。直观地看,算法输出的数字只有0、1、2这三个,而且对任何一个都没有偏袒,那么显然每个数字的概率都是1/3,那让我们来严格地计算一下。

以输出0为例,看看概率是多少。x的第一个有效数值是通过Rand5得到的。Rand5返回0的概率是1/5,如果这事儿发生了,我们就得到了0,否则只有当Rand5返回3或4的时候,我们才有机会再次调用它来得到新的数据。第二次调用Rand5之后,又是有1/5的概率得到0,2/5的概率得到3或4导致循环继续执行下去,如此反复。因此概率的计算公式为:

p=====15+25×(15+25×(15+25×(?)))15×∑∞i=0(25)i15×11−2515×5313

喏,计算表明,Rand3输出0的概率确实是1/3,对于另外两个数字也是一样的。

那么这段代码是不是一个算法呢,它是否满足算法的有穷性呢?我不能确定,虽然它不停机的概率是0,然而这个概率是一个极限值,唉,回去复习极限知识先。

【2013年11月7日添加】今天想到,对于上面那个函数,需要再了解一下它消耗的时间。具体来讲,就是要知道平均每调用一次Rand3,相当于调用了多少次Rand5。根据算法可以知道,Rand3函数执行一次,有3/5的概率是只调用一次Rand5就能停机;刚好调用两次Rand5后停机的概率是(2/5) * (3/5)。类推下去,刚好调用k次Rand5后停机的概率应该是(2/5) ^ (k-1) * (3/5)。根据这个概率分布,可以计算出停机前Rand5被调用次数的数学期望,即

∑k=1∞k×p(k)=∑k=1∞k35(25)k−1=35×1(1−25)2=53

可见,Rand3函数每运行一次,平均需要调用1.67次Rand5。

更一般地,当我们依据上述算法,将一种分布的随机信号转换成另外一种随机信号时,如果每消耗m个源信号,就有p的概率可以产生一个目标信号,那么平均来讲,停机前需要使用的源信号数据个数的期望为:

∑k=1∞k⋅m⋅p⋅(1−p)k−1=mp

【2013年11月7日添加结束】

改变一下题目,如果要求利用Rand5编写Rand7怎么办?很简单,用两个Rand5可以拼出Rand25,然后就用前面的方法即可:

1
2
3
4
5

def Rand7():
    x = -1
    while not 0 <= x < 21:
        x = Rand5() * 5 + Rand5()
    return x % 7

1
2
3
4
5
6
7
8
9

int Rand7()
{
    int x;
    do
    {
        x = Rand5() * 5 + Rand5();
    } while (x >= 21);
    return x % 7;
}

【2013年11月7日】可以直接算出,按照这种方法,平均每运行一次Rand7,需要调用Rand5的次数。这里m等于2,p等于21/25,所以最后的结果是50/21,大约是2.38。

时间: 2024-11-02 07:41:08

利用等概率Rand5产生等概率Rand3的相关文章

【XSY2518】记忆(memory)(状压dp,概率与期望,概率dp)

题面 Description 你在跟朋友玩一个记忆游戏. 朋友首先给你看了\(n\)个长度相同的串,然后从中等概率随机选择了一个串. 每一轮你可以询问一个位置上的正确字符,如果能够凭借已有的信息确定出朋友所选的串,那么游戏就结束了,你的成绩就是所用的轮数. 由于你实在太笨,不会任何策略,因此你采用一种方法,每次等概率随机询问一个未询问过的位置的字符. 现在你想知道,在这种情况下,你猜出结果所需的期望次数. Input 第\(1\)行包含一个整数 \(n\),表示串的个数. 第 \(2\sim n

概率dp (背包+概率) 背包的多一点

题意:XX想抢劫银行,当危险率低于P的时候才能行动,现在给出每家银行的金钱mi和危险率pi,求最多能获得多少金钱: 题解:危险率是P,那么安全率就是1-P,那么XX抢劫的所有银行的安全率之积就不能小于1-P,这样就变成了一个01背包的裸题. 1 #include<cstdio> 2 #include<algorithm> 3 #include<string.h> 4 #include<math.h> 5 using namespace std; 6 cons

概率/随机数算法

0-1等概率问题 问题描述 一个随机数产生器以概率P生成0,以概率(1-P)生成1,怎样生成等概率的0和1? 主要思路 如果用这个产生器产生两个位,出现00的概率为P^2,出现01的概率为P(1-P),出现10的概率为P(1-P),而出现11的概率为(1-P)^2.故而可以用10表示1,01表示0,从而保证生成0和1的概率是相同的. 代码实现 int generate01(int (*func)()) { if (func == NULL) return -1; int num1 = -1; i

1637 - Double Patience (概率DP)

一道状态较多的概率DP,想要表示所有的状态显然要拓展几个维度表示九堆牌当前的状态 . 但是这么写太复杂,所以我们不妨用一个vector来储存状态,将dp数组用一个map来表示,即 map<vector<int> ,double> d; 利用vector可以作为函数参数传递这个优点,将大大节省代码量 . 概率很好求,在每一次迭代中,寻找所有可以转移的状态数tot,那么状态转移就是d[i] = sum(d[i-1])/tot . 也就是全概率公式 . 递归边界是当所有牌都被摸走了,返回

(四)概率

老习惯,还是先给出该章节的思维导图让大家先有个总体的概念 对于基础概念就不在此赘述,挑当中的几个easy混淆的点和关键点说说 首先便是相互排斥事件与独立事件,非常多人会将两者混淆.有个样例非常好的说明了两者不是一回事: 假设两个事件是相互排斥事件,当中之中的一个被确定已经发生,则还有一事件发生的概率降为0,显然两者是相关的. 其次为何要引入条件概率呢? 这是由于现实生活中相互独立的事件非常少,大多数事件的发生都与其它事件有关联,计算他们发生的概率时我们就须要採用条件概率的方式,当然假设两个事件是

程序员眼中的统计学(3)】概率计算:把握机会

概率计算:把握机会 作者 白宁超 2015年10月13日23:23:13 摘要:程序员眼中的统计学系列是作者和团队共同学习笔记的整理.首先提到统计学,很多人认为是经济学或者数学的专利,与计算机并没有交集.诚然在传统学科中,其在以上学科发挥作用很大.然而随着科学技术的发展和机器智能的普及,统计学在机器智能中的作用越来越重要.本系列统计学的学习基于<深入浅出统计学>一书(偏向代码实现,需要读者有一定基础,可以参见后面PPT学习).正如(吴军)先生在<数学之美>一书中阐述的,基于统计和数

隐马尔科夫模型HMM(二)前向后向算法评估观察序列概率

隐马尔科夫模型HMM(一)HMM模型 隐马尔科夫模型HMM(二)前向后向算法评估观察序列概率 隐马尔科夫模型HMM(三)鲍姆-韦尔奇算法求解HMM参数(TODO) 隐马尔科夫模型HMM(四)维特比算法解码隐藏状态序列(TODO) 在隐马尔科夫模型HMM(一)HMM模型中,我们讲到了HMM模型的基础知识和HMM的三个基本问题,本篇我们就关注于HMM第一个基本问题的解决方法,即已知模型和观测序列,求观测序列出现的概率. 1. 回顾HMM问题一:求观测序列的概率 首先我们回顾下HMM模型的问题一.这个

概率--学习朴素贝叶斯分布

概率是一种基于事件发生可能性来描述未来趋势的数学工具.其本质就是通过过去已经发生的事情来推断未来事件,并且将这种推断放在一系列的公理化的数学空间当中进行考虑.例如,抛一枚均质硬币,正面向上的可能性多大?概率值是一个0-1之间的数字,用来衡量一个事件发生可能性的大小.概率值越接近于1,事件发生的可能性越大,概率值越接近于0,事件越不可能发生.天气预报员通常会使用像"明天80%的可能性会下雨"这样的术语来对降雨进行预测,这里70%或者0.7就是下雨的概率.在现实生活中,要么下雨,要么不下雨

随机事件 概率 赌博 泊松分布

概率论是一门研究随机现象规律的数学分支.其起源于十七世纪中叶,当时在误差.人口统计.人寿保险等范畴中,需要整理和研究大量的随机数据资料,这就孕育 出一种专门研究大量随机现象的规律性的数学,但当时刺激数学家们首先思考概率论的问题,却是来自赌博者的问题.数学家费马向一法国数学家帕斯卡提出下列的 问题:“现有两个赌徒相约赌若干局,谁先赢s局就算赢了,当赌徒A赢a局[a < s],而赌徒B赢b局[b < s]时,赌博中止,那赌本应怎样分才合理呢?”于是他们从不同的理由出发,在1654年7月29日给出了