我需要生成一个非常大的范围内的随机数,128位整数,并且我将生成许多它们。我会生成很多这样的内容,以至于我无法在内存中列出生成的数字列表。
我还要求生成的数字不重复,或者至少重复的概率很小。
是否有算法执行此操作?
答案 0 :(得分:0)
构建一个128位linear congruential generator或linear 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要求而分心。那些涉及重播,因此可以多次产生相同的数字(这是更随机的,但它是你想要避免的)。