最大長のLFSR ( PRBSシーケンスなど) は適合しますか?
たとえば、PRBS31 シーケンス (x 31 +x 28 +1) は、すべての 31 ビット整数 (0 を除く) を 1 サイクル (2 31 -1 ビット長)に 1 回だけ生成することが保証されています。
実装もかなり簡単です。
public int prbs31(int state) {
int feedback = ((state >> 30) ^ (state >> 27)) & 1;
return ((state << 1) | feedback) & 0xffffffff;
}
何らかの (ゼロ以外の) 整数から始めて、prbs31
連続して呼び出します - 前の結果を渡します (これはフィードバック レジスタです!)
PRBS31 は、非常に優れた統計的にランダムなビット パターンを生成します (真のランダムビット パターンと混同しないでください)。
ただし、隣接する値は非常に似ていることに注意してください。上記の方法では、PRBS シーケンスに対して 1 ビットのスライディング ウィンドウを実行します。つまり、隣接するすべての値に 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 を単純に使用することは、非常に予測可能です。この場合、1 つの値を知ることで、将来のすべての値を知ることができます。これにより、この方法はシミュレーション (ゲームなど)には適していますが、暗号化または秘密の意味を持つものには非常に適していません!
個人的には、このメソッドを使用して、ハッシュ テーブルでキーとして使用されるオブジェクトの一意の ID を生成します。