生成随机数而不重复(或消失重复概率)而不存储过去生成的数字的完整列表?

时间:2016-02-03 15:08:03

标签: random

我需要生成一个非常大的范围内的随机数,128位整数,并且我将生成许多它们。我会生成很多这样的内容,以至于我无法在内存中列出生成的数字列表。

我还要求生成的数字不重复,或者至少重复的概率很小。

是否有算法执行此操作?

2 个答案:

答案 0 :(得分:0)

构建一个128位linear congruential generatorlinear feedback shift register生成器。通过适当选择的系数,其中任何一个都将实现完整循环,这意味着在您用完所有结果之前不会重复。

答案 1 :(得分:0)

任何具有128位状态的全周期PRNG原则上都会满足您的需求。遗憾的是,许多这些生成器每次迭代往往只产生32或64位,而其余的状态经历可预测的排列(LFSR是最坏的情况,每次迭代只产生1位)。每个128位状态都是唯一的,但它的许多位将显示与先前状态的微不足道的关系。

这可以通过回火来克服 - 将您可疑质量的PRNG状态置于已知良好的时期,并通过1:1变换对其进行置换以隐藏不那么随机的因素。

例如,借用维基百科上显示的示例xorshift+

static uint64_t s[2] = { 1, 0 };

void random128(uint64_t result[]) {
  uint64_t x = s[0];
  uint64_t y = s[1];

  x ^= x << 23;
  x ^= y ^ (x >> 17) ^ (y >> 26);

  s[0] = y;
  s[1] = x;

此时我们知道s[0]只是s[1]的旧值,如果所有128位都被暴露(通常只有s[1]被暴露),这将是一个可怕的PRNG。为了克服这个问题,我们将结果置换为伪装这种关系(遵循与feistel network相同的原则来确保变换为1:1)。

  y += x * 1630144151483159999;
  x ^= y >> 3;

  result[0] = x;
  result[1] = y;
}

这似乎足以通过死硬。只要原始发生器具有完整(ish)周期,整个发生器也应该是满周期。

回火低质量发电机的合理结论是在计数器模式下使用AES-128。只需运行一个从0到2**128-1(一个极低质量的发生器)的计数器,并使用AES-128和一致密钥(理想的脾气)加密每个值,以便最终输出。

如果您这样做,请不要因完整的加密RNG要求而分心。那些涉及重播,因此可以多次产生相同的数字(这是更随机的,但它是你想要避免的)。