std::uniform_real_distribution 在失去随机性之前可以生成多少个随机数?

How many random numbers can std::uniform_real_distribution generate before losing randomness?

我正在为 Monte Carlo 模拟编写 C++ 代码。因此,我需要生成许多均匀分布在 [0,1) 之间的数字。我包含了以下取自 here 的代码来生成我的号码:

// uniform_real_distribution
#include <iostream>
#include <random>

std::default_random_engine generator;
std::uniform_real_distribution<double> distribution(0.0,1.0);

int main()
{  
    double number = distribution(generator); //rnd number uniformly distributed between [0,1)
    return 0;
}

因此,每次我需要一个新号码时,我都会拨打 distribution(generator)。 我 运行 我的 Monte Carlo 模拟得到很多样本结果。结果应该围绕真实平均值(未知)呈正态分布。当我 运行 进行卡方拟合优度检验以检查它们是否呈正态分布时,我的样本结果有时无法通过检验。这里的关键词是 "sometimes",所以这让我觉得我调用了 distribution(generator) 太多次,最后我失去了生成数字的随机性。我说的是每次模拟中生成的 10^11 个数字。

这可能吗?如果我在调用它之前用 distribution.reset() 重置分配怎么办?这能解决我的问题吗?

感谢您的任何建议。

STL使用的随机数生成算法在标准中没有规定,所以在不知道使用的随机数生成算法的情况下,无法确定随机序列有多长。

它可能是 Mersenne twister 或 CMWC 等一小部分已知的又好又快的发电机之一。

对随机数生成器进行评级的方法有很多种,但在你的问题中,我认为你想知道周期 - 数字重复之前的时间。该周期也将取决于初始条件。

一个很好的标准 CMWC 发生器,CMWC 4096 的周期为 2^131104。标准梅森发生器 MT19937 的周期为 2^19937。

但是,如果您使用的 STL 实现使用了选择不当的算法,那么所有的赌注都会落空。

在每次调用之前重新播种,甚至经常重新播种,特别是如果种子选择不当,将会破坏生成器的统计属性。通常最好只播种一次,然后从那里调用它。

如果随机数生成器有时没有通过测试,那么测试太弱了。例如,如果一个测试有 99% 的置信度,那么一个完美的随机数生成器应该有大约 1% 的概率会失败。

例如,考虑一枚完全公平的硬币。如果翻转 1,000 次,平均会出现 500 次正面朝上。如果你想用它来测试随机性,你可以计算一个公平硬币在一定时间百分比内落入的值范围。然后确保您的随机数生成器不会比预期更频繁地失败测试。

您的测试方法——期望随机数生成器每次都能通过每个测试——只有在您的测试非常弱时才有效。这将使糟糕的随机数生成器过于频繁地通过,这不是一种好的测试方法。

真实故事:我实现的一个随机数生成器经过 an independent testing lab 的严格测试。他们对其进行了 100 次测试,每次测试使用数百万个样本并测试各种特性。每个测试都有 99% 的置信度。 RNG通过了3次测试,均在预期范围内,因此通过了认证的测试部分。一个 RNG 在绝大多数时间都通过了这些极其严格的测试,这表明它是一个非常非常好的 RNG,也许是完美的。很难编写一个通过任何这些测试的损坏的 RNG。

您需要计算完美 RNG 无法通过测试的概率,然后查看您的 RNG 显示的失败率是否接近预期。

请注意,随机序列的强度取决于生成器,而不是分布。

关于 default_random_engine the reference 说“一种发电机,至少可以为相对随意、不专业、and/or 轻量级使用提供可接受的引擎行为"...可能不是你想要的。

按照提示,可以换成std::mt19937,我不是专家,不知道能用多久才会失去随机性。

要更新生成器的随机性,您可以使用 std::random_device 并不时将其用于 seed() 生成器。在某些实现中(您必须检查)random_device 甚至使用 CPU 的特殊指令来生成 "hard" 随机数作为种子。 las,您不能每次都简单地重新播种,因为这样的硬件生成速度非常慢。