最大长度LFSR(例如PRBS序列)是否适合?
例如,PRBS31 序列 (x 31 +x 28 +1) 保证每个 31 位整数(0 除外)在一个周期内仅生成一次(即 2 31 -1 位长)
它也很容易实现:
public int prbs31(int state) {
int feedback = ((state >> 30) ^ (state >> 27)) & 1;
return ((state << 1) | feedback) & 0xffffffff;
}
您从一些(非零!)整数开始,然后prbs31
连续调用 - 将先前的结果传回。(它是一个反馈寄存器!)
PRBS31 生成非常好的统计随机位模式(不要与真正的随机位模式混淆)
但是,请记住相邻值将非常相似 - 上面建议的方法在 PRBS 序列上执行一位滑动窗口,这意味着每个相邻值都有 30 位共同(尽管在不同的地方)
但是我们可以每次将寄存器推进 31 步,如下所示:
// initial seed, doesn't really matter which value you use
// as long as it's not zero (remember that the sequence goes over
// all the possible 31-bits values anyway)
private static final int SEED = 0x55555555;
private int state = SEED;
public int nextInt() throws SequenceCycleException {
for (int i = 0; i < 31; ++i) {
state = prbs31(state);
if (state == SEED) {
throw new SequenceCycleException();
}
}
return state;
}
这将生成一个看起来随机的整数序列,长度为 (2 31 -1)/31
免责声明:单个 LFSR 的幼稚使用是高度可预测的。在这种情况下,知道一个值就可以知道所有未来的值——这使得这种方法对模拟(例如游戏)非常有用,但对于任何具有密码或秘密意义的东西也非常不利!
就个人而言,我使用这种方法为在哈希表中用作键的对象生成唯一 ID。