c++ - 如何使用按位运算将随机 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 之间表示的所有值。
解决方案
由于双数的编码方式,很难直接在 (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]。
推荐阅读
- c# - Microsoft.Graph.ServiceException:代码:methodNotAllowed
- java - 如何将@ConfigurationProperties 与记录一起使用?
- python - 使用烧瓶在 html 中上传图片并在 doc 中放置图片时出现错误请求
- php - 刷新PHP后将变量保留在类中
- php - 无法更新 laravel 模型可见属性
- javascript - 为什么我有这个错误“StartTag:无效的元素名称”?
- graph - networkx 图的默认顺序?
- haskell - 局部关闭在haskell中更有效吗?
- d3.js - D3.js 对焦+刷机
- amazon-dynamodb - 带有 value 关键字的 Dynamo DB 扫描字段