10

我做了这样的实验——用 C 和 C# 制作了 1000 万个随机数。然后从随机整数的15位中计算每个位设置了多少次。(我选择了 15 位,因为 C 只支持最多 的随机整数0x7fff)。

我得到的是: 在此处输入图像描述
我有两个问题:

  1. 为什么有 3 个最可能的位?C万一比特8,10,12是最有可能的。并且C#在位6,8,11是最有可能的。

  2. 似乎 C# 最可能的位大多被移动了 2 个位置,然后与 C 最可能的位相比。为什么是这样 ?因为 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() 的次数时得到的结果: 在此处输入图像描述
所以许多人注意到 - 结果不可重现,不应认真对待。(除非以某种形式确认 C/C# PRNG 足够好:-))。

4

3 回答 3

10

这只是常见的或花园采样变化。

想象一个实验,你反复掷硬币十次。您不会期望每次都获得五个正面。这取决于采样变化。

同样,您的实验也会受到抽样变化的影响。每个位遵循相同的统计分布。但抽样变化意味着您不会期望在 0 和 1 之间有精确的 50/50 分割。

现在,您的情节误导您认为这种变化在某种程度上很重要或具有意义。如果您从 0 开始绘制图表的 Y 轴,您会对此有更好的理解。该图表如下所示:

在此处输入图像描述

如果 RNG 行为正常,那么每个位将遵循概率为 0.5的二项式分布。该分布具有方差np(1 − p)。对于您的实验,这给出了 250 万的方差。取平方根得到大约 1,500 的标准差。因此,您可以简单地从检查结果中看出,您看到的变化并没有明显异常。您有 15 个样本,没有一个样本与真实平均值的标准差超过 1.6 个。这没什么好担心的。

你试图辨别结果中的趋势。你说过有“3个最可能的位”。这只是您对该示例的特定解释。尝试使用不同的 RNG 种子再次运行程序,您将获得看起来有些不同的图表。他们仍然具有相同的品质。有些位比其他位设置得更多。但是不会有任何可辨别的模式,当您将它们绘制在包含 0 的图表上时,您会看到水平线。

例如,这是您的 C 程序为98723498734.

在此处输入图像描述

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

于 2012-05-23T15:29:28.637 回答
2

您知道偏差约为 2500/5,000,000,降到 0.05%?

于 2012-05-23T15:25:46.237 回答
1

请注意,每个位的频率差异仅变化约 0.08%(-0.03% 至 +0.05%)。我不认为我会认为这很重要。如果每一点都完全一样可能,我会发现 PRNG 非常有问题,而不仅仅是有点问题。您应该期望在应该或多或少建模随机性的过程中存在一定程度的差异......

于 2012-05-23T15:33:09.987 回答