c++ - 分布在 -DBL_MAX 和 DBL_MAX 之间的随机 double

标签 c++ c++11 stl

我正在尝试为所有可表示的有限值生成具有大致相等概率的随机 double 。我相信这类似于随机签名的 exponential_distributionuniform_distribution 将不起作用,因为可表示的 double 不是均匀分布的。我有这个 hacky 代码,似乎可以做我想做的事:

#include <cmath>
#include <iostream>
#include <random>

template < class GEN >
double double_distribution (GEN& generator)
{
    using gen_type = typename GEN::result_type;
    static_assert (sizeof (gen_type) == sizeof (double), "");
    union {gen_type g; double f;} result;
    do {
        result.g = generator();
    } while (!std::isfinite (result.f));
    return result.f;
}

int main() {
    std::mt19937_64 mt ((std::random_device())());
    for (int n = 0; n < 10; ++n) {
        std::cout << double_distribution (mt) << ' ';
    }
    std::cout << '\n';
}

但我想知道是否有一种更简单的方法可以使用 STL 现有的 RandomNumberDistribution 类之一来对此进行近似?

最佳答案

如果您假设一个 64 位 IEEE double ,这里有一个方法。 (对于 double 的不同表示,您应该能够修改此基本方法。)

64位分为1位符号,11位指数,52位小数。像 NaN 和 inf 这样的特殊值由指数位的特殊值表示。您在这里有两个基本选择:

  1. 从所有可能的 64 位组合的集合中生成一个随机数(就像在适当大小的整数类型上的统一),并从中设置你的 double 。在这种情况下,您有时会绘制一个对应于例如 NaN 的数字。您需要丢弃它们并重新绘制或接受它们,具体取决于您是否希望返回 NaN。 (听起来你的情况可能不是这样。)

  2. 在一次绘制中生成符号和小数部分的位,然后分别绘制指数。如果你这样做,你应该能够修改你的绘图,这样你就不会拉出 NaN 值 - 特殊值似乎对应于指数的极值,所以这相当于改变你的绘图范围整数,我认为许多软件包都可以轻松支持它。在这种情况下,您不必“重新绘制”来避免特殊值,但您可能会在每次绘制时得到一些“额外”位,因为您可能最终会从整数类型的分布中提取(位数为 8 的倍数),但符号 + 分数使用 53,指数仅使用 11。您可能会做一些聪明的事情来节省这些位,以便在下一次抽取中使用一次绘制中“丢弃”的位。您必须仔细考虑以确保这不会在您的绘图之间引入依赖性,但我认为这应该没问题。

如果效率对您来说不是什么大问题,那么#1 看起来更易于实现。如果您需要效率,那么 #2 可能会更好,尽管可能以更复杂的代码为代价。

关于c++ - 分布在 -DBL_MAX 和 DBL_MAX 之间的随机 double ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42163618/

相关文章:

c++ - 通过在 C++ 中使用连接调用它来编辑字符串

c++ - OpenGL 着色器 GLSL 中的颜色按位移位

c++ - 为什么函数指针不被通用引用捕获?

c++ - std::move 的逆函数是否存在?

c++ - "No match for operator-"简单迭代器差异错误

c++ - OpenMP 中的共享 vector

C++ 函数对象无法使用 std::for_each 创建 sum (VS2012)

c++ - 从 multimap (C++) 中完全删除元素

c++ - 临时延长生命周期

c++ - 为什么 cURL 使用 zlib?