从图片看出伪随机数的周期性

今天尝试用代码生成了一张大小为1024*1024,每个像素的RGB值都是随机数的图片(以下图片经过了一定程度的压缩):

random1

本应该是完全随机的图案,但是在图片中却可以明显地看出许多竖线,这显然是伪随机数的周期性导致的。

由于图片的宽度是1024像素,所以我猜测其中的周期一定和1024这个数有关。我决定看一看随机数以1024为周期的统计特性。

我把每个颜色值的生成方法改为连续获取1024个随机数,算出总和,并对256取余数,得到了这幅图片:

random2

从这幅图片中可以明显地看出很强的周期性!

我再把统计的周期取大一些,例如32768,仅仅通过简单的计算就可以看出随机数分布的不均匀。写这样一段C语言程序:

运行的结果:

01010101010101010101010101010101……

我又做了一种尝试——在一张1024*1024的黑色背景图片上,从坐标为(512,512)的点开始,每一次取随机数除以4的余数,对应于上下左右四个方向,在图片上随机行走,用渐变的颜色画出轨迹。

代码如下:

运行结果:

random3

可以看出整张图片只有一小部分被颜色覆盖了,而且图案的对称性很强。

这些代码是在Windows上用Dev-C++中的GCC编译器编译的,如果换一种环境,随机数的周期性还会这么强吗?

我又试了Visual Studio 2012,效果和之前完全一样。

但是当我在Ubuntu上使用GCC编译时,情况发生了变化。

首先我编译运行了那段很短的C语言代码,程序给出的结果中找不到规律。我又运行了随机行走的代码,效果如下:

random4

可以看出颜色随机覆盖了几乎整个屏幕,毫无规律可循。这说明Ubuntu下的GCC编译器使用的随机数算法比Windows下的要好。

用随机颜色生成的随机图案还是很美的。

《从图片看出伪随机数的周期性》有7个想法

  1. VC++內建的rand()可能是出於效率考量,是使用Linear congruential generator來產生偽隨機數的,GCC改成Mersenne twister了。

    如果想在VC++中使用Mersenne twister,要用MT19937

  2. linux下随机数生成比较好。建议试试windows下的 CryptGenRandom(而非cryptRandom ), 有结果给我发个邮件,谢谢

    1. 我试过了,效果和linux下一样,看不出周期。测试的源代码和效果图已经发邮件了

      1. 师弟把测试windows下的CryptGenRandom和cryptRandom代码和图片也更新放到这篇文章里吧。

  3. Pingback: Si-Yuan's

发表评论

电子邮件地址不会被公开。 必填项已用*标注