| 
注册时间2009-5-22最后登录1970-1-1威望 星金币 枚贡献 分经验 点鲜花 朵魅力 点上传 次下载 次积分38756在线时间 小时 
 | 
 
 发表于 2010-2-27 13:21:34
|
显示全部楼层 
| 晃动鼠标时,鼠标指针的坐标参数变化是一列性质良好的随机数。 
 这列随机数的产生速度比抛硬币、投骰子快多了
  
 千万别用C++标准库里自带的rand()函数,这个rand()函数太挫了。
 
 比如下面这段代码……
 生成的16MB的文件拿winRAR软件压缩一下就只剩522KB了,说明rand()生成的随机数很糟糕。复制代码#include<cstdio>
#include<cstdlib>
int rand16()        //生成一个0到15的随机数
{
        return rand()%16;
}
char rand_ch()        //把两个0到15的随机数拼成一个字节
{
        return rand16()*16+rand16();
}
int main(int i)
{
        freopen("d:\\rand.txt","wb",stdout);
        for(i=0;i<16777216;i++)        //输出16M字节
                printf("%c",rand_ch());
        return 0;
}
 难怪拿去做各种不确定性试验时,出现一连串雷同的试验结果。
 
 如果说一个随机数列是好的,那么它:
 
 每一项的取值都是分布均匀的;
 相邻两项组成的二元组是分布均匀的;
 相邻三项组成的三元组是分布均匀的;
 ……
 相邻N项组成的N元组是分布均匀的。
 
 如果上述条件有一个不满足,就说明这个数列的熵值未达到最大,可以用哈夫曼编码进行压缩。
 
 WinRAR软件已经在一定程度上实现了这一功能,所以可以根据WinRAR软件的压缩结果来衡量一个随机数列的好坏。
 
 对于好的随机数列,其熵值一定是最大化的,WinRAR软件是一个字节都压不动的。
 
 要加长随机数列的周期,可以通过添加辅助变量的方法。
 
 把上述代码修改如下:
 虽然只做了小小的改动,但生成出来的16MB的文件用winRAR压缩,一个字节都压不动了。复制代码#include<cstdio>
#include<cstdlib>
unsigned int s;        //辅助变量
int rand16()        //生成一个0到15的随机数
{
        s=s*s+s/13+rand();
        return s%16;
}
char rand_ch()        //把两个0到15的随机数拼成一个字节
{
        return rand16()*16+rand16();
}
int main(int i)
{
        freopen("d:\\rand.txt","wb",stdout);
        for(i=0;i<16777216;i++)        //输出16M字节
                printf("%c",rand_ch());
        return 0;
}
 因为添加辅助变量后,即使rand()函数跑完了一个周期,但辅助变量的值与初值不同,所以生成出来的数是不同的。
 
 要等到rand()函数跑完了一个周期的同时,辅助变量恰好回到原始初值,才是一个完整的周期。
 
 显然这个周期远比单独使用rand()函数的周期长。
 
 添加辅助变量需要额外的运算量。
 
 所以要根据实际的需要来选取合适的辅助变量个数以及计算公式,在生成速度与周期长度两者之间进行权衡。
 | 
评分
查看全部评分
 |