10

たとえば、Java が23をシードとして 使用して9 3 2 5 6という疑似ランダム シーケンスを生成する場合、どうすれば逆を行うことができますか? つまり、シーケンス9 3 2 5 6から23を取得します。

または、特定のシーケンスにシードを割り当てるにはどうすればよいですか?

データベースがあれば簡単に実行できます - シーケンスにランダムなキーを割り当てるだけです

INSERT INTO SEQUENCE_TABLE VALUES (RANDOM_KEY, SEQUENCE)

ただし、データベースの使用が許可されていない場合、そのようなことを行うための公式はありますか?

4

5 に答える 5

6

乱数ジェネレーターのポイントは、これが不可能だということです。SecureRandom は特に暗号的に強力になるように設計されていますが、一般的に言えば、乱数ジェネレーターを作成していて、これが可能または簡単である場合、それは間違っています。

とはいえ、Java の組み込みの Random クラスでは不可能ではない可能性があります。(ただし、SecureRandom は別の話です。) しかし、それには膨大な量の数学が必要になります。

より具体的に言うと、特定の疑似乱数ジェネレーターに対して、必要なことを行う多項式時間アルゴリズムが存在する場合、リンクされたウィキペディアの記事で説明されている「次のビットテスト」に失敗します。次に生成される要素。

于 2012-01-20T05:12:09.530 に答える
6

java.util.Random によって使用されるシードを回復することは確かに可能です。この投稿では、Random の線形合同式の背後にある数学について説明します。次に、nextInt() から返された最後の 2 つの整数から現在のシードを検出する関数を示します。

public static long getCurrentSeed(int i1, int i2) {
        final long multiplier = 0x5DEECE66DL;
        final long inv_mult = 0xDFE05BCB1365L;
        final long increment = 0xBL;
        final long mask = ((1L << 48) - 1);

        long suffix = 0L;
        long lastSeed;
        long currSeed;
        int lastInt;

        for (long i=0; i < (1<<16); i++) {
                suffix = i;
                currSeed = ((long)i2 << 16) | suffix;
                lastSeed = ((currSeed - increment) * inv_mult) & mask;
                lastInt = (int)(lastSeed >>> 16);

                if (lastInt == i1) {
                        /* We've found the current seed, need to roll back 2 seeds */
                        currSeed = lastSeed;
                        lastSeed = ((currSeed - increment) * inv_mult) & mask;
                        return  lastSeed ^ multiplier;
                }
        }

        /* Error, current seed not found */
        System.err.println("current seed not found");
        return 0;
}

この関数は、rand.setSeed() で使用できる値を返し、i1 と i2 で始まる数値の疑似乱数シーケンスを生成します。

于 2013-11-25T01:23:33.947 に答える
2

a をStringシードとして使用しても問題ない場合は、これを使用できます。

String seed = "9 3 2 5 6";

次に、ジェネレーターは次のようになります。

String[] numbers = seed.split(" ");

本当にJavaで「乱数」ジェネレーターをリバースエンジニアリングしたいのなら、それはかなり難しいでしょう(私は思います)。

可能であれば、逆の方法で実行することをお勧めします。シードから開始し、シーケンスを生成し、そこから作業を進めます。

于 2012-01-20T04:55:56.007 に答える
0

任意の数字のシーケンスを取得し、元の数字を保存せずにその数字のシーケンスを再生成できる短い (固定長?) キーを決定しますか? 残念ながら、あなたが望むものは技術的に不可能です。理由は次のとおりです。

これは圧縮の特殊なケースです。長いデータ シーケンスがあり、小さな情報からロスレスに再作成できるようにしたいと考えています。あなたが要求していることが可能であれば、スタックオーバーフロー全体を単一の整数に圧縮することができます (非常に長いものではありますが、ウェブサイト全体を一連の数字にシリアル化できるためです!)

残念ながら、数学はそのようには機能しません。特定のシーケンスには、エントロピーの特定の測定値 (そのシーケンスの複雑さの平均量) があります。そのシーケンスを無損失で再現するには、少なくともそのエントロピーを表すのに十分な情報をエンコードできなければなりません。

特定のシーケンスでは、実際には長い特定のシーケンスを生成できるシードが存在する場合がありますが、それは、そのシードを取得して特定の数値シーケンスを生成するハードコードされた数学関数があるためです。ただし、値の任意のシーケンスを取り、そのようなシードを生成するには、シードと、そのシードからそのシーケンスを生成できる関数の両方が必要になります。これらの両方をエンコードするには、予想よりもはるかに多くのデータを取得する必要があります。

于 2012-01-20T05:24:34.983 に答える