我有兴趣在C中生成快速随机布尔值(或等效的伯努利(0.5)随机变量)。当然,如果有一个具有良好统计行为的快速随机生成器,问题“随机伯努利样本(0.5) “很容易解决:在(0,1)中统一采样x
,如果1
,则返回x<0.5
,否则返回0
。
假设速度是最重要的,现在我有两个问题/考虑因素:
许多随机双打生成器首先在特定范围m
内均匀生成整数[0,M]
,然后只返回除m/M
。检查m < M/2
(此处M/2
是否已修复,以便我们保存一个部门)不会更快吗?
答案 0 :(得分:2)
提取说随机数的最后一位可能会造成严重破坏,因为线性同余生成器可以在奇数和偶数 1 之间交替。像clock() & 1
这样的方案也会有可怕的相关平原。
考虑基于Donald Kunth的快速和脏的生成器的解决方案:对于uint32_t I
,序列
I = 1664525 * I + 1013904223;
和2 * I < I
是产生布尔图的条件。在这里,我依赖于I
的环绕行为,这种行为应该在一半的时间内发生,并且避免了可能昂贵的划分。
测试I <= 0x7FFFFFFF
不那么浮华,可能会更快,但中点的硬编码并不完全令人满意。
1 我在这里的发电机确实。
答案 1 :(得分:1)
我对生成快速随机布尔值感兴趣
使用LCG可能很快,但由于OP仅需要bool
结果,因此请考虑从合理的生成器中一次仅提取1位,并将其余部分保存以供日后使用。 @Akshay L Aradhya
extern uint32_t lcg64_temper(uint64_t *seed); // see R.. code
static uint64_t gseed; // Initialize this in some fashion.
static unsigned gcount = 0;
bool rand_bool(void) {
static uint32_t rbits;
if (gcount == 0) {
gcount = 32; // I'd consider using 31 here, just to cope with some LCG weaknesses.
rbits = lcg64_temper(&gseed);
}
gcount--;
bool b = rbits & 1;
rbits >>= 1;
return b;
}