.net 为什么伪随机数生成器不太可能连续生成54个大数字?

rfbsl7qr  于 2023-03-13  发布在  .NET
关注(0)|答案(1)|浏览(129)

考虑一个概率为 p 的事件。该程序检查在事件发生之前有多少次失败的尝试,并保存总数的直方图。例如:如果 p 为0.5,那么这就像问 * 一枚硬币连续多少次出现反面才出现正面 *,如果 p 的值较小,我们会预期在成功之前会有许多次失败。
正在测试的实现基本上是:while (!(rand.NextDouble() < p)) count++;
这是 count 的结果直方图。

在x=54处的不规则性是显而易见的。由于某种原因,对于一行中恰好产生54个大于或等于 p 的随机数的序列来说,它的可能性大约是的一半。
我在这个测试中检查的实际 p 是1/32。(这并不重要,只要它足够小,可以得到一些可测量的54作为结果。)我正在计算总共10000000次成功。(似乎也不重要。)我使用什么随机种子也不重要。
显然,这是. NET中的Random.NextDouble函数所使用的伪随机数生成器的一个怪癖。但是我想知道
为什么**这个原本均匀的数据在如此奇怪的特定和一致的地方会有如此引人注目的单个尖峰?随机数发生器,使生成正好54个大数在一行后面的一个小数字一半的可能性,任何其他序列长度?
我本以为会有更多的非均匀异常,因为它退化,而不仅仅是这一个尖峰。
下面是生成此数据集的代码:

using System;

namespace RandomTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Random rand = new Random(1);
            int numTrials = 10000000;
            int[] hist = new int[512];
            double p = 1.0 / 32.0;
            for (int i = 0; i < numTrials; ++i) {
                int count = 0;
                while (!(rand.NextDouble() < p)) {
                    count++;
                }
                if (count > hist.Length - 1) {
                    count = hist.Length - 1;
                }
                hist[count]++;
            }
            for (int i = 0; i < hist.Length; ++i) {
                Console.WriteLine("{0},{1}", i, hist[i]);
            }
        }
    }
}

如果它是相关的,这是Windows x86上的.Net Framework 4.7.2。

8zzbczxx

8zzbczxx1#

我在framework 4.8上运行了你的代码,发现第28点是异常值
plot of generated data
然后我再次运行,没有任何变化,58是异常值
2nd plot of data
我猜您所察觉到的问题的原因是随机生成器是随机的。
每次运行代码都会产生不同的结果,而且异常值出现的位置似乎是随机的。
既然我们知道离群值是随机的,我们就可以得出结论,它不是某一行代码中的错误。正因为如此,我们可以假设随机离群值可能仅仅是由生成器选择了一个明显比其他数少的数的偶然性引起的。随机性的随机性。

相关问题