首页 > 解决方案 > 范围为零的 uniform_int_distribution 进入无限循环

问题描述

对于单元测试,我实现了一个模拟随机数生成器。我相信这是UniformBitGenerator的有效实现(模拟实际上使用谷歌模拟来设置返回operator(),但它的行为相同)。

struct RNG
{
    using result_type = size_t;
    static result_type min() { return 0; }
    static result_type max() { return std::numeric_limits<result_type>::max(); }
    result_type operator()() { return max(); }
};

std::uniform_int_distribution现在我使用这个模拟从range中采样[a, b], a == b。我相信这是允许的,我在这里发现的分布参数的唯一限制是b >= a. 所以我希望下面的程序能够打印5.

int main()
{
    auto rng = RNG();
    auto dist = std::uniform_int_distribution<>(5, 5);
    printf("%d\n", dist(rng));
    return 0;
}

相反,它进入 STL 内部的无限循环,反复从生成器中提取数字,但无法在指定范围内找到数字。我测试了不同版本的不同(当前)编译器(包括clang、gcc、icc)。RNG::max也可以返回其他值(例如 42),不会改变任何东西。

我正在测试的真实代码将一个随机索引绘制到一个容器中,该容器可能只包含一个元素。检查这种情况很容易,但这是一种罕见的情况,我想避免这种情况。

我是否遗漏了 STL 中的 RNG 规范中的某些内容?我会惊讶地发现所有编译器中都有一个错误......

标签: c++randomlanguage-lawyerstd

解决方案


通常通过拒绝抽样来实现均匀分布。您不断请求随机数,直到获得符合条件的随机数。您设置了无法满足条件的情况,因为您的随机数生成器非常非随机,因此会导致无限循环。


推荐阅读