Rand7生成Rand10
AI摘要: 本文介绍了如何使用数学原理和C++代码生成等概率的随机数。首先,通过数学公式$(randX() - 1) * Y + randY()$可以生成等概率的$[1, X * Y]$范围内的随机数。证明过程基于$randX()$和$randY()$分别生成$[1, X]$和$[1, Y]$之间的等概率随机数。联合概率表展示了如何从这些随机数中采样得到均匀分布的$[1, XY]$之间的随机数。接着,文章提供了使用C++编写的代码示例,演示了如何通过构造特定表达式来生成在指定范围内的均匀随机数。然而,这种方法效率较低,因为只有当采样到$[1, 10]$之间时才会停止,而$[11, 49]$之间的数会被丢弃。为了提高效率,文章提出了一种优化方法,通过模除操作将范围缩小到$[1, 10]$,并进一步优化为只采样$[41, 49]$之间的数,从而提高了效率。最后,文章还探讨了从进制的角度解决问题的方法,指出如果给定$rand1()$只能生成$[0, 1]$之间的均匀随机数,那么可以通过二进制编码的方式生成$[a, b]$之间的均匀随机数。
数学原理
数学定律: 可以生成等概率的范围内的随机数
证明:由于可以生成之间的等概率随机数, 可以生成之间的等概率随机数
那么可以在 中随机采样 ,
因此所构成的联合概率表为:
所以,从表中可以看到,能够均匀采样出之间的随机数
代码
根据上面公式,如果想通过生成, 可以先构造出, 这样就做到了在之间均匀随机采样
代码如下:
using namespace std;
int main() {
while(1) {
int rand_value = (rand7() - 1) * 7 + rand7();
if(rand_value >= 1 && rand_value <= 10){
cout << rand_value<< endl;
break;
}
}
return 0;
}
但是这种方法的效率偏低,因为只有采样到之间才结束,而之间的数都会被抛弃
进一步优化,之间都能够进行均匀随机采样,使用模除可以放缩到
using namespace std;
int main() {
while(1) {
int rand_value = (rand7() - 1) * 7 + rand7();
if(rand_value >= 1 && rand_value <= 40){
cout << rand_value % 10 << endl;
break;
}
}
}
这样就只有之间的数被抛弃,效率会教上者更高
进制解法
上面的解法在于数学公式的证明和实用,另外一种解法是从进制的角度来思考
首先来看,如果给定, 只能生成 之间的均匀随机数,如何构造的均匀随机数 ,这种情况就无法直接套上面的公式。
如果从二进制的角度来看,可以很容易生成之间的均匀随机数,因为可以对二进制的每一位采用随机函数。那么就可以很容易生成之间的均匀随机数
现在将题目改成给定, 希望生成的均匀随机数,那么这就是用7进制来随机生成之间的数