std::uniform_real_distribution 总是返回无穷大

时间:2021-03-29 12:22:06

标签: c++ random numeric-limits

当我运行此代码时:

double getRandomDouble() {
    static std::mt19937 entropy_ = std::mt19937();
    std::uniform_real_distribution<double> distribution;
    distribution.param(typename decltype(distribution)::param_type(std::numeric_limits<double>::lowest(),
                                                                   std::numeric_limits<double>::max()));
    return distribution(entropy_);
}

它总是返回无穷大(至少在 GCC8.1 和 clang 11.0.1 中。在 MSVC 14.16.27023 中它断言)

Here is a working demonstration in GodBolt

我希望这个函数返回任何随机的双精度值,这里发生了什么?

3 个答案:

答案 0 :(得分:5)

参数的选择违反了proc divmod(a, b: int): (int, int) = (a div b, a mod b) let (x, y) = divmod(8, 5) echo x, " ", y 的前提条件(参见§26.6.9.2.2.2)。

前提条件是 std::uniform_real_distributiona ≤ b,其中 b - a ≤ numeric_limits<T>::max()a 是分布的最小值和最大值。使用 bnumeric_limits<double>::lowest() 会违背这一点。

正如 Ted 所建议的,使用 numeric_limits<double>::max()a = -max()/2.0 会是更好的选择。

答案 1 :(得分:1)

uniform_real_distribution 的强制实现基本上是均匀分布在 [0,1) 中,然后通过乘以 [a,b) 再添加 (b-a) 映射到 a

这是一个很好的面向速度的实现,但是当应用于极端情况时它失败了。在您的情况下,计算 b-a 会导致无穷大,随后整个计算失败。

答案 2 :(得分:-1)

您有一个数字问题:分布使用概率函数:1 / (b - a),在这种情况下,b - a 超出了 double 的范围(这意味着 {{1 }},因此所有数字都是inf)。您可以通过降低限制来修复它,如下例所示。

此外,您始终使用新的随机数生成器,并且由于种子相同,因此始终生成相同的数字。您可以将生成器置于函数外部,以便它继续生成新数字,或者更好地关联一个随机设备。

inf

您可以对其进行测试here

相关问题