随机打乱函数性能测试

首先,对于随机打乱函数,有两个性能指标,一个是随机性,一个是时间;在具体测试的内容上,又分为从2~9的大小的数组的打乱。下面是测试的函数,统计了每一位=个数出现在每一位的具体次数,每次测试的组数都是n*100000(保证每个位置出现的平均次数都是100000)。

int Source[9] = { 1,2,3,4,5,6,7,8,9 };
int Destination[9] = { 0 };
int Count_Array[10][10] = { 0 };
int start = clock();
for (int i = 0; i < 100000 * n; i++)
{
Disorganize(Destination, Source, n);
for (int loc = 1; loc <= n; loc++)
{
Count_Array[loc][Destination[loc - 1]]++;
}
}

1.基本方法

首先在n=9时,测试结果如下。基本保证了随机性。


不过当n=8时,出现了我意想不到的结果:


这说明每个数出现的位置都是一定的。在经过大量的测试后,我最后发现这个bug是我最初的随机数生成器造成的。下图为我连续打印Random(8)的结果,发现形成了一个以8为循环的序列。而当测试其他数时,发现2,4也有这样的特性,也会形成以2和以4为周期的序列。同理,在后面的16,32,64,128等等的数都有这样的特性。所以最终得到结论,当n=2^k(k=1,2,3,……)时,一次线性同余所生成的随机数会形成一个以n为周期的循环。同时,我也测试的其他的数,发现只要不是2的次方,就不会形成明显的循环。所以我最后在Random函数中加入了这句话,保证了2,4,8的时候的随机性。

if (edge == 2 || edge == 4 || edge == 8) return (randSeed) % (3 * edge) / 3;


最终在随机函数修改过后,所有的数的测试都有了良好的随机性。

2.大量的交换位置

首先测试了n=9时,交换10次的情况:


显然随机性很差;

然后是交换次数为20的情况

依然能够明显看出没有做到每项的随机;

当交换30次的时候:


这时的随机性达到了要求,同时在测试n等于其他数时随机性也得到了保证;

3.每次减少能填数的位置

n=9的时候:


可以看出,此方法的随机性较差,同时在时间上也比前两种方法慢;

在n等于其他数时,得到的随机性也比较差;至于第四种方法跟本方法的实现完全一样,就不进行测试了;

5.取哈希

这个方法是我在思考的时候觉得最有趣的方法,但最终的结果却不令人满意;

n=9时:


而在n=8时,随机性会完全崩溃;至于其他的n,当n为偶数的时候随机性就会崩溃。


而至于随机性消失的原因我也无从而知,或许是那个随机取哈希值的原因?但是不随机取每次以1为哈希值时,单次的结果总会出现连续的递增序列,这样单次的随机性就又无法保证了。所以最后这种方法被我舍弃,留在这里仅供参考。

最终结果

在经过测试后,得出具有良好的随机性和运行速度的反而是最简单、最好想的两种方法。所以我决定在这两种方法中挑选一个。

单次的时间测试可能不太准确,所以我决定对它们进行大量的测试求平均值,选取n=9时,每组100w次,一共20组;

代码如下:

int times = 20;
int sum = 0;
for (int t = 0; t < times; t++)
{
int start = clock();
for (int i = 0; i < 1000000; i++)
{
Disorganize(Destination, Source, n);
}
int end = clock();
sum += end - start;
printf("消耗时间:%dms\n", end - start);
}
printf("平均时间:%dms\n", sum / times);

第一种:


第二种:


由于删去了每次的数据统计,只看运行速度,所以会比之前快;

可以看到,第二种方法只比第一种快一点点。

所以在最终版本中,我采用了第一种方法来作为的我的随机打乱函数,因为第一种的随机性相当的稳定。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值