由扔骰子看平均概率生成

来源:互联网 发布:网络协议概念 编辑:程序博客网 时间:2024/06/05 05:09

由扔骰子看平均概率生成

昨天读到一个帖子,说如何通过扔骰子的方法得到7件事的平均概率情况(扔骰子只能得到6件事的均概率),其中一种解法为,扔两次,分别记为x,y,则定义计算式m=(x-1)*6+y,可得到m的范围为1-36,且m为均概率事件,则剩下要做的就很简单了,去掉36这一项,剩下的mod7即可。

通俗点说若想得到7件事的均概率,则必须能够通过计算得到m件事的均概率且m>=7,(上题m=36),然后再进行取舍。

因此,若想通过骰子得到4件事的均概率,则不需要定义新的计算式,因为掷骰子本身就是6件事的均概率(m=6且6>4),则对掷出的结果去掉5,6两项,剩下的mod4即可。

还有一种通解但是成功概率小很多的情况(本题求7的均概率成功率比较大,因为只有36这一种情况要舍弃),若需要n件事的概率,则先求得n转换为六进制数所需要的位数m,m就是转动骰子的次数(每转一次确定一位),转动m次后得到m个数字,计算得到六进制随机值p,如果p>n,则抛弃这次的投掷,否则认为是成功的投掷,但这样会大大降低得到可用解的概率,所以还需引申公式。

进而推广成为平均概率生成的问题,已知函数randM()可以等概率生成1~m的数字,试编写函数randN(),要求等概率生成1~n的数字

根据以上结论,分两种情况

1、若n<=m,则比较简单,通过取余便可得到(注意去掉多余的项数)

randN()

{

     m=randM();

     while(m>n)

     {

              m=randM();

     }

     return m;

}


 

2、若n>m,首先计算k,使得m^k>n>m^(k-1),k即为利用原函数的次数(上题即为掷骰子次数),利用掷k次骰子(用k次原函数)可得到m^k次种均概率事件且m^k>n,为方便后面讨论,记m^k=x.此时,依然有两种接法。

法一,生成概率比较低,但思路简答,将生成的x种均概率记为x种不同的情况,取其中的前n种即可(后面的舍弃)  注:此时虽然生成x种不同的均概率,但并非1~x的均概率事件

法二,生成概率较高,但需要一步运算,分别记k次利用randN()得到的数为k1,k2…kk,则通过公式k1+(k2-1)·k+(k3-1)·k^2……得到1~x的均概率,通过此种方法舍弃的情况可以减少,从而大大提高命中率

下面举一个例子,已知rand4(),要求生成1~31的均概率

rand31()

{

     int x=rand4();

     int y=rand4();

     int z=rand4(); //因为4^3>31>4^2,所以原概率要利用3次,即k=3

     int m=x+(y-1)*4+(z-1)*64; //则m为1-64的均概率

     if(m>62)

              重新生成x,y,z,重新计算m;

     else

              return   (m%31)+1;成功得到1-31的均概率,且命中率为31/32

 

}

 

解释:虽然此类解法可以生成1-m的均概率,但不能保证概率之和相加为1,因此有命中率一词,生成结果有效,不需要重新生成的概率越大,命中率越高。显然,在同样能实现1-m均概率的各种方法中,命中率应该越高越好。


原创粉丝点击