【问题标题】:How many random numbers can std::uniform_real_distribution generate before losing randomness?std::uniform_real_distribution 在失去随机性之前可以生成多少个随机数?
【发布时间】:2015-05-28 19:21:39
【问题描述】:

我正在为蒙特卡洛模拟编写 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)。 我运行我的蒙特卡洛模拟以获得许多样本结果。结果应该正态分布在真实平均值周围(这是未知的)。当我运行卡方拟合优度检验以检查它们是否呈正态分布时,我的样本结果有时无法通过检验。这里的关键词是“有时”,所以这让我觉得我打电话给distribution(generator) 太多次了,最后我失去了生成数字的随机性。我说的是每次模拟中生成的 10^11 个数字。

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

感谢您提出的任何建议。

【问题讨论】:

  • 您可以为 rng 设置种子值
  • default_random_engine 使用的 Mersenne Twister 算法有一个period of 2^19937 - 1。 10^11 甚至不应该让它流汗。
  • @MarkRansom default_random_engine 使用的算法是实现定义的。
  • 那么,有疑问,使用 mt19937?
  • 分布没有随机性,生成器有随机性。这一切都取决于发电机。 @zneak 有正确的想法。

标签: c++ random


【解决方案1】:

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

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

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

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

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

【讨论】:

    【解决方案2】:

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

    它可能是一小部分已知良好且快速的生成器,例如 Mersenne twister 或 CMWC。

    对随机数生成器进行评级的方式有很多种,但在您的问题中,我认为您想知道周期 - 直到数字重复多长时间。该时间段还将取决于初始条件。

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

    但是,如果您使用的 STL 实现使用选择不当的算法,那么所有的赌注都将失败。

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

    【讨论】:

      【解决方案3】:

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

      关于default_random_engine the reference 说“一个至少为相对随意、不熟练和/或轻量级使用提供可接受的引擎行为的生成器”......可能不是你想要的。

      按照建议,您可以将其替换为std::mt19937,我不是专家,所以我不知道您可以使用多长时间才能失去随机性。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多