前提:假设我们拥有一个随机数发生器rand7均匀产生1-7之间随机整数,如何构造rand10均匀产生1-10之间的整数。
分析:由于rand7是均匀产生,因此由均匀分布的概念来说,产生1-7之间的概率是相同的分别是1/7,因此在该条件下,为了满足计算需要可以适当丢弃1-7之间的数字,而不会影响其他数字获取的概率。
假设:rand7由该函数生成:
//生成1-7之间的随机数
int rand7() {
int a = 0;
return a = rand() % 7 + 1;
}
为了获取rand10这里提出2种方法:
方法一:
第一步:将1-7数字中的7移除掉,剩下1-6分别为一半奇数一半偶数,奇偶概率相同
第二步:将1-6数据分别于1进行按位与操作,将1-6转换成0-1
第三步:4次循环,每次由1-6数字产生0-1数字,生成0-15范围数字
第四步:由于0-15生成概率相同,丢弃掉0与11-15保留1-10
下面是伪代码实现:
//将1-6数据同1进行按位与运算,将奇偶转换为0-1
int GenBit() {
int a = 0;
while ((a = rand7()) == 7);
return a & 1;
}
//生成1-10随机数
int GenOneToTenNormal() {
int x;
do {
x = 0;
for (int i = 0; i < 4; i++) {
x = x << 1 | GenBit();
}
count++;
} while (x <= 0 || x > 10);
return x;
}
方法二:
第一步:将1-7数字分别减去1变为0-6
第二步:进行2次随机数生成,组成一个二位7进制数(00-66)
第三步:将7进制数据转为10进制数据(0-48)
第四步:去掉40到48让个位数字(0-9)出现的概率相同
第五步:对0-39数据与10进行求余,得到0-9数据
第六步:对0-9进行加1操作变为1-10
下面是伪代码:
//通过7进制数据生成1-10
int GenOneToTenSmart() {
int x = 0;
while ((x = (rand7() - 1) * 7 + (rand7() - 1)) >= 40);
return x % 10 + 1;
}
下面是整体测试程序:
#include "stdio.h"
int main() {
int i = 0;
int resultNormal = 0;
int resultSmart = 0;
while (i++ < 20) {
resultNormal = GenOneToTenNormal();
printf("resultNormal=%d\n", resultNormal);
resultSmart = GenOneToTenSmart();
printf("resultSmart=%d\n", resultSmart);
}
}
//生成1-7之间随机数
int rand7() {
int a = 0;
return a = rand() % 7 + 1;
}
//第一种方式获取0-1之间数据
int GenBit() {
int a = 0;
while ((a = rand7()) == 7);
return a & 1;
}
//第一种方式获取1-10之间数据
int GenOneToTenNormal() {
int x;
do {
x = 0;
for (int i = 0; i < 4; i++) {
x = x << 1 | GenBit();
}
} while (x <= 0 || x > 10);
return x;
}
//第二种方式获取1-10之间数据
int GenOneToTenSmart() {
int x = 0;
while ((x = (rand7() - 1) * 7 + (rand7() - 1)) >= 40);
return x % 10 + 1;
}
参考资料: