随机整数中最可能的位

10

我进行了这样的实验——从C和C#中生成1000万个随机数,然后统计每个随机整数中15位比特中设置的次数。(我选择15位,因为C仅支持随机整数到0x7fff)。

我得到了这个结果: enter image description here
我有两个问题:

  1. 为什么有3个最可能的比特?在C情况下,比特8,10,12最有可能。而在C#情况下,比特6,8,11最为常见。

  2. 此外,似乎C#最有可能的比特位置与C最有可能的比特位置相比多了2个位置。这是为什么?因为C#使用其他RAND_MAX常量吗?


C的测试代码:

void accumulateResults(int random, int bitSet[15]) {
    int i;
    int isBitSet;
    for (i=0; i < 15; i++) {
        isBitSet = ((random & (1<<i)) != 0);
        bitSet[i] += isBitSet;
    }
}

int main() {
    int i;
    int bitSet[15] = {0};
    int times = 10000000;
    srand(0);

    for (i=0; i < times; i++) {
        accumulateResults(rand(), bitSet);
    }

    for (i=0; i < 15; i++) {
        printf("%d : %d\n", i , bitSet[i]);
    }

    system("pause");
    return 0;
}

以下是 C# 的测试代码:

static void accumulateResults(int random, int[] bitSet)
{
    int i;
    int isBitSet;
    for (i = 0; i < 15; i++)
    {
        isBitSet = ((random & (1 << i)) != 0) ? 1 : 0;
        bitSet[i] += isBitSet;
    }
}

static void Main(string[] args)
{
    int i;
    int[] bitSet = new int[15];
    int times = 10000000;
    Random r = new Random();

    for (i = 0; i < times; i++)
    {
        accumulateResults(r.Next(), bitSet);
    }

    for (i = 0; i < 15; i++)
    {
        Console.WriteLine("{0} : {1}", i, bitSet[i]);
    }

    Console.ReadKey();
}

非常感谢!! 顺便说一下,操作系统是Windows 7,64位结构以及Visual Studio 2010。

编辑
非常感谢@David Heffernan。我犯了几个错误:

  1. C和C#程序中的种子不同(C使用零,而C#使用当前时间)。
  2. 我没有尝试使用不同的Times变量值进行实验,以研究结果的重现性。

当分析第一个比特设置的概率如何取决于调用random()的次数时,这就是我得到的结果: enter image description here
因此,正如许多人注意到的那样 - 结果不可重复且不应被认真对待。 (除非作为某种形式的确认,即C / C# PRNG已足够好 :-) )。


2
我已经记不起来学校里的统计课程了,但你需要找出异常值是统计学上的显著性还是仅仅是随机误差的结果。你永远不可能得到完美的分布。 - Mike Weller
3
这些结果可以再现吗?那会让我感到惊讶。如果您多次运行相同的测试,我怀疑在后续运行中,不同的位将变得“更有可能”和“ less probable”。 - abelenky
4
我刚刚意识到图表上的比例不是0到1000000,而是加减少于百分之一的分数。现在我感到很少惊讶了。 - Rawling
1
“利用统计数据说谎是一件有趣的事情!”(http://www.dansdata.com/goop.htm)请看其中关于“误导机”的部分。 - Li-aung Yip
4
顺便说一句,用条形图来绘制数据可能更好,而不是线图。在这个例子中,线条在视觉上暗示了相邻位之间存在关系,但实际上并不存在。(Edward Tufte 可能对此有更多的见解。) - Li-aung Yip
显示剩余7条评论
3个回答

10

这只是普通的抽样变异。

想象一下,你反复投掷十次硬币的实验。你不会期望每次都得到五个正面。这是由于抽样变异造成的。

同样,你的实验也会受到抽样变异的影响。每个部分都遵循相同的统计分布。但是抽样变异意味着你不应该期望0和1之间有一个完美的50/50分割。

现在,你的图表让你误以为变异在某种程度上具有显著性或意义。如果你将图表的Y轴起始值设置为0,你可以更好地理解这一点。那个图表看起来像这样:

enter image description here

如果随机数发生器表现正常,那么每个比特都将遵循0.5的二项分布。该分布具有方差np(1-p)。对于您的实验,这给出了一个250万的方差。取平方根得到约1500的标准偏差。因此,您可以从检查结果简单地看出,您所看到的变化并没有明显超出正常范围。您有15个样本,没有一个样本的真实均值超过1.6个标准差。这没什么好担心的。
您试图辨别结果中的趋势。您曾说过有“3个最可能的比特”。那只是您对这个样本的特定解释。尝试使用不同的随机数种子再次运行程序,您将会得到看起来略微不同的图表。它们仍然具有相同的质量。某些比特被设置得比其他比特更多。但不会有任何可辨认的模式,并且当您在包含0的图表上绘制它们时,您将看到水平线。
例如,这是您的C程序使用随机种子98723498734输出的内容。

enter image description here

我认为这应该足以说服你运行更多的试验。当你这样做时,你会发现没有任何特殊的位被给予优待。


+1. 但是人们希望随着 N 趋近于无穷大,期望的比率会收敛于50%。 - Oliver Charlesworth
@Oli 是的,但在这里我们有一个有限的 N。因此总是存在抽样变异性。 - David Heffernan
非常感谢你提供的出色统计解释。然而,统计学并不能解释具体实验结果的“原因”。而对于我来说,最有趣的是结果的原因。我可以说使用精确的种子来调用random()函数会导致偏爱位被设置吗?(这将解释伪随机性中的“伪”部分) - Agnius Vasiliauskas
1
每个具体的实现都会有一些比其他更多的位。但你无法预测哪些位会占据上风,不同的种子会赢得不同的位。在考虑随机过程时,试图解释单个实现是很难的。你在评论中所问的正好类似于询问为什么你抛硬币时出现了正面而不是反面。 - David Heffernan
1
@David:没错,但我认为伪随机数生成器和真随机数生成器之间的区别实际上是随机性这个棘手概念中相当重要的一部分,不应该被忽视。一个好的伪随机数生成器的定义质量在于它“看起来”能够生成随机数据,所以最重要的是要确定提问者展示的数据是否看起来是随机的,也就是它的统计属性是否与真随机数生成器的输出可能的统计属性一致。至于这个测试,在这方面说,基本上是的,我完全同意你回答的主要部分。 - Steve Jessop
显示剩余5条评论

2

你知道偏差是约为2500/5,000,000,相当于0.05%吗?


3
在假设每一位都是均匀随机的情况下,方差为 n*p*q = n / 4,这意味着在五百万个位中有两千五百个是 2和一点标准偏差。 - Steve Jessop
我并不是指统计学中的偏差(因为我几乎从未涉及这个主题,也几乎不知道任何具体的内容),但还是感谢你的补充。 - CodeCaster
我用了500000000个迭代来运行这个程序,并得出了约为0.003%的结果。 - paul

1
请注意,每个比特的频率差异仅约为0.08%(-0.03%至+0.05%)。我不认为这是显著的差异。如果每个比特的概率完全相等,我会认为这个伪随机数生成器是非常不可靠的,而不是有点值得怀疑。在模拟随机性的过程中,您应该预计一定程度的变化...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接