考虑一个以概率p发生的事件。该程序检查在事件发生之前进行了多少次失败的试验,并保留总数的直方图。例如:如果p是 0.5,那么这就像问硬币在出现正面之前连续出现了多少次反面?使用较小的p值,在我们获得成功之前,我们预计会有很多失败。
正在测试的实现本质上是: while (!(rand.NextDouble() < p)) count++;
这是count的结果直方图。
立即明显的是 x=54 处的不规则性。出于某种原因,连续生成一系列大于或等于p的恰好 54 个随机数的可能性大约是其应有的一半。
我在这个测试中检查的实际p是 1/32。(这并不重要,只要它小到足以获得一些可测量的 54 个作为结果。)而且我正在计算 10000000 次总成功。(似乎也无关紧要。)我使用的随机种子也无关紧要。
显然,这是Random.NextDouble.NET 中函数使用的伪随机数生成器的一个怪癖。但我想知道为什么这个原本统一的数据在如此奇怪的特定和一致的地方有如此惊人的单一峰值?这个特殊的伪随机数生成器是什么,它可以连续生成 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]);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果相关,这是 Windows x86 上的 .Net Framework 4.7.2。
小智 1
我在框架 4.8 上运行了你的代码,发现第 28 点是异常值:

然后,我再次运行它,没有任何改变,58是异常值:

我猜测您所感知到的问题的原因是随机生成器是随机的。
每次运行代码都会产生不同的结果,并且异常值的位置似乎是随机的。
由于我们知道异常值是随机的,因此我们可以得出结论,这不是特定代码行中的错误。因此,我们可以假设随机异常值可能只是由于生成器选择的数字明显少于其他数字而引起的。随机性中的随机性。