今天同学出了这样一个题,让我们大家来讨论,大家都提出了很多方法,最后在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。