快速C随机布尔生成器

时间:2018-05-09 14:03:57

标签: c performance random boolean

我有兴趣在C中生成快速随机布尔值(或等效的伯努利(0.5)随机变量)。当然,如果有一个具有良好统计行为的快速随机生成器,问题“随机伯努利样本(0.5) “很容易解决:在(0,1)中统一采样x,如果1,则返回x<0.5,否则返回0

假设速度是最重要的,现在我有两个问题/考虑因素:

  1. 许多随机双打生成器首先在特定范围m内均匀生成整数[0,M],然后只返回除m/M。检查m < M/2(此处M/2是否已修复,以便我们保存一个部门)不会更快吗?

    1. 有没有更快的方法呢?最后,我们在这里要求减少统计特性:我们可能仍然对很长一段时间感兴趣,但是,例如,我们不关心分布的均匀性(只要大约50%的值在该范围的前半部分)。

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

基于@R..@R..代码的示例。

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;
}