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