我有一个随机数生成器,如下所示。
uint64_t s[ 2 ];
uint64_t next(void) {
uint64_t s1 = s[ 0 ];
const uint64_t s0 = s[ 1 ];
s[ 0 ] = s0;
s1 ^= s1 << 23; // a
return ( s[ 1 ] = ( s1 ^ s0 ^ ( s1 >> 17 ) ^ ( s0 >> 26 ) ) ) + s0; // b, c
}
事实上,我想在 (0,1) 范围内获得 double 。一种选择是在我的代码中执行此操作
#define M_RAN_INVM64 5.42101086242752217003726400434970855e-20
[..]
double u1;
u1 = next()*M_RAN_INVM64;
- 我担心我会失去精度,而且这取决于平台。
- 我不想得到值 0 或 1。
一个选项是将 next() 转换为 signed long long,乘以 M_RAN_INVM64,然后加 0.5。然后我可以添加 2^(64)/2 以确保我永远不会得到我认为的 0。
最佳答案
接受答案后:
double
数字呈对数分布。 double
0.25 到 0.5 的数量与 0.5 到 1.0 的数量一样多 - 假设基数为 2 double
。
假设 double
是 IEEE binary64:...
要在 [0.0 到 1.0) 范围内获得 double
的均匀(线性)分布,只能使用 2^53 个值。所以从 next()
uint64_t u1 = next();
u1 >>= 11;
// or
u1 &= 0x001FFFFFFFFFFFFF;
if (u1 == 0) ThrowOutZero();
// convert to (0.0 to 1.0)
double d = u1 / 9007199254740992.0; // Divide by 2^53
关于c - 如何将 unsigned long long 转换为 double,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24023799/