代码改变世界

随机数生成 :转http://conflict.diandian.com/post/2013-02-28/40049884387

2014-04-21 02:05  crazyxiazi  阅读(273)  评论(0)    收藏  举报

其实 一个很有用的原则 那就是 进制

      在我们平时的编程中,系统都会给我们提供随机数生成器rand(),它可以产生我们限定范围内的一个随机数,而在一些面试题中往往会让我们通过限定的随机生成器去构造更完善的,这里面是有技巧的,下面通过两个面试题来说明一下:

1. 已知一个随机数发生器A,产生0的概率是p,产生1的概率是1-p,要求构造以下随机数生成器,  效率尽可能的高。

  1. 产生0,1概率分别为1/2的随机数生成器B;

  2. 产生概率为1/n的1~n范围内的随机数生成器C。

 

核心思想就是从随机数发生器产生的一列数中找到概率相同的某些数代表我们将要生成的数,即抛弃一些随机产生的数,留下那些概率相同的。上题的解法如下:

  1. 让随机数生成器A产生两个随机数,产生的可能序列为00,01,10,11,而它们对应的概率为p^2, p(1-p), (1-p)p, (1-p)^2,由此我们可看出01和10产生的概率是一样的,那么我们的随机数产生器B就出现了:让A执行两次,若产生00或11时,抛弃继续循环,若产生01,则认为产生了1,若产生10,则认为产生了0

  2. 随机数生成器C的构造则需要一些技巧,我们现在用B来构造C。由于B生成0,1的概率是一样的,随机发生k次形成的序列所代表的的十进制数概率都是一样的,比如说,我们要一个1~5的随机数生成器C,让B随机产生3次(2^3 > 5),生成的序列为000,001,010,011,100,101,110,111,而概率都是1/8,这样我们将它们序列代表的值与我们想要生成的随机数一一对应,而0,6,7则丢弃,就构成了一个可以生成1~5的随机数生成器。

2. 已知有个rand7()的函数,返回1到7随机自然数,让利用这个rand7()构造rand10() 随机0~10

网上有很多这道题的解法,但是是有问题,下面我将分别列举一下错误的解法和正确的解法

错误的解法:

让rand7()执行两次,产生0~49之间的数的概率都是一样的,即 a1 = rand7() * rand7();对10求余,但是我们会发现产生的概率并不相同,那么我们抛弃一些数字,1~40对10求余产生的1~10的概率是一样的(注意:求余数产生0的认为产生的是10),参考代码如下:

int rand10()  
{  
  int a10;  
  do 
  {  
      a10 = rand7() * rand7() ;
  } while (a10 > 40);
    return a10 % 10 + 1;
}

 

如果你没有发觉到上述算法的问题,你可以分别算一下产生1,6,11这三个数的概率是多少。(分别是1/49, 4/49, 0)

正确的解法:

其实上面的问题可以转换成用进制转换问题:用七进制表示1~10,进制转换的公式是:

a10 = bn*7^n + bn-1 * 7^(n-1) + ... + b1 * 7^1 + b0

而随机发生器的作用就是产生各个位数的bi,对于1~10,我们需要两个随机产生器 R1, R0,它们分别产生b1, b0。那么它们可以产生的范围是8~56(1*7+1 ~ 7*7+7), 总计49个数字,而且这49个数字出现的概率是相同的。然后我们截取40个数字,如 10~50,然后对10求余即可.

int rand10()
{
    int a10;
    do {
        a10 = rand7() * 7 + rand7();
    } while (a10<10 || a10 >50);
                                                 
    return a10%10 + 1; 
}

代码大家都能看懂,下面我将证明一下为什么通过我这种方式可以得到等概率出现的数,这里面只牵扯到高中的概率知识。

证明:

假设随机发生器rand7产生数字为一个事件,两个随机发生器R1,R0分别为事件A,B。产生8~56范围为事件C,其中A,B是相互独立的。

则R1产生数字1,2,3,4,5,6,7的概率分别是:

P(A = 1) = 1/7

P(A = 2) = 1/7 

P(A = 3) = 1/7 

......

P(A = 7) = 1/7 

事件B也是一样的,这里就不再列举。

现在大家可以试一下事件C = 8,9,10,11, ......, 54,55,56这些数字的概率是不是相等的。

P(C= 8) = P(A=1) * P(B=1) = 1/49

P(C=9)  = P(A=1) * P(B=2) = 1/49

......

P(C=56) =P(A=7) * P(B=7) = 1/49

证毕