首页 > 解决方案 > 如何使用按位运算将随机 uint64_t 转换为范围 (0, 1) 内的随机双精度

问题描述

我能达到的最好的是这个(它给出的结果在 0 ~ 0.5 之间):

uint64_t const FRACTION_MASK = 0x1fffffffffffffull;
uint64_t const EXPONENT_BITS = 0x3fc0000000000000ull;
double to01(uint64_t i) {
    i = (i & FRACTION_MASK) | EXPONENT_BITS;
    return reinterpret_cast<double&>(i);
}

我试错了那些神奇的数字。我什至不知道这个是否可以产生一个 double 可以在 0 到 0.5 之间表示的所有值。

标签: c++

解决方案


由于双数的编码方式,很难直接在 (0, 1) 范围内生成一个好的随机数,但在 [1, 2) 范围内很容易得到一个 [@GemTaylor]。

double to_01(uint64_t i)
{
    constexpr uint64_t mask1 = 0x3FF0000000000000ULL;
    constexpr uint64_t mask2 = 0x3FFFFFFFFFFFFFFFULL;
    const uint64_t to_12 = (i | mask1) & mask2;
    double d;
    memcpy(&d, &to_12, 8);
    return d - 1;
}

请注意,并非所有位i都用于生成结果。另请注意,此函数仅适用于 64 位 IEEE-754 浮点数 [@geza]。


推荐阅读