随机数:关于用Rand7生成Rand10的最准确的算法(MS中的一道题)--仿真证明

来源:互联网 发布:电子数据交换原理 编辑:程序博客网 时间:2024/04/29 21:39

今天同学出了这样一个题,让我们大家来讨论,大家都提出了很多方法,最后在CSDN上搜了一个相关的帖子,感觉上面写的算法挺杂的,想看原帖的如下

其实有一个非常有说服力的算法,实现也比较也比较简单。就是利用我们学计算机的基础--进制(2进制,8进制等)思想来完成的。

前提有一个普适的规律:1、任何一个进制类型都可以表示任意一个数字。

                                            2、进制的每一位上的数,出现的值范围都是一样的,如2进制,每位中只能出现0,1;8进制,每位中只能出现0~7;7进制,每位上出现0~6中的数是概率都是相等的。

基于以上的2个规律,得到了以下两种较准确的算法。

1.取0~39内的数除于4取整,得到范围为0~9(每个取值的数都是机会均等的)

代码如下:

int rand10(){    int i;    int j;    int Tworesult;//表示的两位7进制,其十进制的范围是0~48     do    {       i = rand7() - 1;       j = rand7() - 1;       Tworesult = i * 7 + j;    }    while(Tworesult >= 40);    return Tworesult/4 + 1;}

仿真100w次的结果如下:

1次数:99938
2次数:99523
3次数:100191
4次数:99723
5次数:100169
6次数:99864
7次数:100732
8次数:99854
9次数:100134
10次数:99872

如果将上面程序的最后一句改为 Tworesult %10 + 1;

100w次的仿真结果如下:

1次数:100075
2次数:100447
3次数:99600
4次数:99535
5次数:100685
6次数:99633
7次数:100121
8次数:99920
9次数:100034
10次数:99950

两者的结果其实是一样的

2.取40~49的数取模10(mod(10)),得到范围的0~9(每个取值的数都是机会均等的)

int rand10(){    int i;    int j;    int Tworesult;//表示的两位7进制,其十进制的范围是0~48     do    {       i = rand7() - 1;       j = rand7() ;       Tworesult = i * 7 + j;    }    while(Tworesult < 40);    return Tworesult%10 + 1;}

100w的仿真结果如下:

1次数:100171
2次数:100506
3次数:99827
4次数:99713
5次数:99875
6次数:99979
7次数:100454
8次数:100043
9次数:99675
10次数:99757

总结:
这两种方法都达到了题目要求的效果,但是对于大量数据统计而言,算法1的时间效率明显要高于算法2