当我运行此代码时:
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
我希望这个函数返回任何随机的双精度值,这里发生了什么?
答案 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_distribution
和 a ≤ b
,其中 b - a ≤ numeric_limits<T>::max()
和 a
是分布的最小值和最大值。使用 b
和 numeric_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。