目录
1、问题定义
已知有一个函数能够产生1-N1之间的的随机数(等概率),通过此函数将其改造成产生1-N2之间的随机数(等概率)。设randN1()为产生1-N1之间的随机数的函数,需要将其改造成randN2()。
2、分下列两种情况进行讨论
情况一:若N1 >= N2时
我们可以用一个例子来讨论这个问题,如给定的函数产生1-50之间的随机数,要将其改成生成1-15之间的随机数。则可以这样考虑,若要将1-50之间的数变为1-15之间的数只需要对15取余运算即可,但是50并不是15的整数倍数,因此无法保证等概率。我想你已经想到了解决办法,即取1-50之间15的最大整数倍数进行取余运算(即45),而大于45的数则舍弃并重新运算。
randN2(){
if(randN1() > 45) return randN2();
else return randN1() % 15 + 1;
}
情况二:若N1 < N2时
此时产生的随机数范围比要改造生成的随机数范围小,那么可以先对其进行范围扩大改造,具体方法如下:
1)构造式子(randN1() - 1 ) * N1,那么其变为生成0,N1,2N1,......,(N1-1)N1之间的数
2)再通过第一步的式子构造(randN1() - 1) * N1 + randN1(),那么会生成1 - N1^2之间的数
3)若N1^2 >= N2则可以参照情况一进行计算,否则返回步骤1)继续扩大构造成1 - (N12)2之间的数,直至满足情况一
3、典型例题:给定产生1-5的随机数,求1-7的随机数函数
// 由random5()构造 random7()
int random7() {
int x = 5 * (random5() - 1) + random5();
if (x > 21) return random7(); // 筛选的过程
return x % 7 + 1;
}
综上所述 , int x = 5 * (random5() - 1) + random5(); 也就是相当于 random25() ,为了保证概率相同,即取1-25之间7的最大整数倍数进行取余运算(即21),而大于21的数则舍弃并重新运算。