【问题标题】:Maximize the number of unique random numbers in a range最大化范围内唯一随机数的数量
【发布时间】:2018-01-16 23:29:22
【问题描述】:

我正在尝试使用 mt19937 引擎和 std::random_device 作为种子源来生成均匀分布的随机数。如果幸运的话,我会从 40 亿个可能的值中得到几十万个唯一数字。我想知道它是否会比这更好。

我尝试使用高分辨率计时器来增加熵,使用 seed_seq (https://stackoverflow.com/a/34493057/5852409) 的随机设备也尝试初始化 mt19937 (https://codereview.stackexchange.com/a/109266) 的所有 624 个状态。但是,没有看到任何改善。

#include <random>
#include <iostream>
#include <set>

void main()
{
    std::random_device rd;
    std::mt19937 engn(rd());
    std::uniform_int_distribution<unsigned int> unidist(0, 0xFFFFFFFF - 1);

    std::set<unsigned int> s;
    auto itr = s.insert(unidist(engn));
    int k = 0;
    while (itr.second)
    {
        itr = s.insert(unidist(engn));
        k++;
    }
    std::cout << k << '\n';
}

【问题讨论】:

  • 从分布中生成样本后,范围内任何一个数字的概率为1/range。包括你刚刚画的数字。因此,据我所知,您提供的代码并没有说明随机数生成器的质量。要查看分布是否真正均匀且没有簇和间隙,您需要运行生成器一段时间,然后执行统计测试以查看这确实是来自均匀分布的样本集的概率。
  • 您不能同时拥有唯一数字和随机数字。您生成的唯一数字越多,它们的随机性就越弱。

标签: c++11


【解决方案1】:

首先,确保您了解birthday paradox。 IE。在十万或十万个数字之后出现重复的事实表明mt19937 存在统计缺陷。

由于这个悖论的粗略估计,即使对于 完美 随机生成器,在大约可能值的平方根之后,重复变得可能,在这种情况下,在大约 2^16 = 65536 个值之后。

其次,请注意熵并不意味着输出的唯一性。想象一下,将一个完全公平的 100 面骰子投掷 100 次。至少一个值出现两次的可能性实际上远大于每个值恰好出现一次的可能性。熵是系统中状态数量的度量。在您的情况下,熵与种子的质量有关(涵盖 PRNG 的许多不同初始状态),而不是输出的唯一性。

第三,如果您有一个必须确保唯一性(例如 ID 或句柄)的用例,但您需要较差的可预测性(即随机性),您基本上有两种选择:

  • 存储“采用”值并在必要时“重新滚动”。还有probabilistic algorithms 可以用更少的 RAM 检测重复项,代价是误报概率很小。
  • 使用更大的——超过两倍多的位——处理空间,并希望不会发生冲突。这适用于不希望发生的偶然碰撞但造成的损害有限(例如导致理论上不必要的昂贵重新计算)的情况。

【讨论】:

    猜你喜欢
    • 2013-11-13
    • 1970-01-01
    • 2011-08-02
    • 1970-01-01
    • 2015-12-22
    • 1970-01-01
    • 2012-08-19
    • 2014-05-08
    • 2016-01-03
    相关资源
    最近更新 更多