为了编程类的目的,我试图说明随机数生成器通常带有标准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万的值,即图形的左下角.果然,他们落在了一起.您只需要真正放大看到它,因为线密度.
老乔治是一个聪明的小孩!