为了编程类的目的,我试图说明随机数生成器通常带有标准C库的缺点,特别是随OSX附带的“坏随机生成器”rand().
我写了一个简单的程序来测试我对光谱测试的理解:
#include <stdio.h> #include <stdlib.h> int main() { int i; int prev = rand(); int new; for (i=0; i<100000; i++) { new = rand(); printf("%d %d\n",prev,new); prev = new; } return 0; }
但是当我画出结果散点图时,我得到的是:
我会期待一些显示更多结构的东西,就像你所发现的那样.我应该绘制更多维度吗?
UPDATE
按照pjs的建议,我放大了部分地块的数字小于1e7,这里是我发现的:
我发现与pjs完全相同的线条.它们似乎是垂直的,但这是不可能的,因为这意味着某些值被rand()“错过”.当我排序 – 数据这是(我的样本)我看到的:
571 9596797 572 9613604 575 9664025 578 9714446 580 9748060 581 9764867 584 9815288 586 9848902 587 9865709 590 9916130 592 9949744 127774 13971 127775 30778 127780 114813 127781 131620 127782 148427 127783 165234 127785 198848 127787 232462 127788 249269
换句话说,这些点在几乎是垂直的线上.
解决方法
线性同余发生器都受到乔治·马萨利亚(George Marsaglia)确定的问题的影响. “马萨利亚定理”说,k元组(长度为k的向量)将落在有限数量的超平面上.边界是m **(1 / k),其中k是元组的大小,m是发电机模数所用的数字.因此,如果模数为(2 ** 31 – 1),并且您正在查看3的集合,则3-d图将显示点不超过(2 ** 31 – 1)的立方根,或约1290架飞机,从正确的方向看.
所有LCG都受Marsaglia定理.一个“好”的一个在上限或接近上限,一个坏的一个比上限好.这就是光谱测试的有效测量,这就是你在维基百科链接中看到的 – 兰德,来自地狱的液晶显示器,产生了只有15架飞机的三联体.
苹果的碳库生成器使用16807作为其乘数,(2 ** 31-1)作为其模数.随着LCG的到来,这不是真的那么糟糕.因此,你的情节没有显示出与RANDU相同的极限.但是,如果您想要质量好的随机数字,请勿使用LCG.
附录
我已经开始从Apple rand()函数中转出了十亿个数字,但是只打印了两个值都不到200万的值,即图形的左下角.果然,他们落在了一起.您只需要真正放大看到它,因为线密度.
老乔治是一个聪明的小孩!