7

疑似乱数ジェネレーター用の適切なランダムシードを生成しようとしています。専門家の意見が聞けると思いました。これが悪い方法なのか、それとももっと良い方法があるのか​​教えてください。

#include <iostream>
#include <cstdlib>
#include <fstream>
#include <ctime>

unsigned int good_seed()
{
    unsigned int random_seed, random_seed_a, random_seed_b; 
    std::ifstream file ("/dev/random", std::ios::binary);
    if (file.is_open())
    {
        char * memblock;
        int size = sizeof(int);
        memblock = new char [size];
        file.read (memblock, size);
        file.close();
        random_seed_a = int(memblock);
        delete[] memblock;
    }// end if
    else
    {
        random_seed_a = 0;
    }
    random_seed_b = std::time(0);
    random_seed = random_seed_a xor random_seed_b;
    return random_seed;
} // end good_seed()
4

7 に答える 7

5

/dev/random から読み取るコードは間違っているようです: 文字バッファーのアドレスを random_seed_a に C スタイルでキャストし (C++ キャスト用のプラグインはこちら)、/dev/random から実際に読み取ったものはすべて無視しています ( *reinterpret_cast<int*>(memblock).

/dev/random はすでに適切なエントロピー ソースである必要があるため、利用可能な場合は、他のデータで値を汚染せず、シードとして直接使用してください。/dev/random に十分なデータがない場合は、時間にフォールバックして、何かと xor するのではなく、それ自体を使用します。

于 2010-04-14T21:02:02.660 に答える
4

優れた疑似乱数ジェネレーターには、「優れた」シードは必要ありません。シード (実行ごとに異なります) はどれも同様に機能します。

システム時刻を直接使用することは問題ありません (そして一般的です)。使用/dev/randomも問題ありません。

疑似乱数ジェネレーターが良くない場合、「良い」シードを選択しても役に立ちません。できれば交換してください。

提案:メルセンヌ ツイスターはかなりよく評価されています。これは、最も限られたシステムでも動作する前駆体です

于 2010-04-14T21:02:37.217 に答える
2

あなたの意見を考慮した後、私が行った変更は次のとおりです。ところで、すべてに感謝します!

unsigned int good_seed()
{
    unsigned int random_seed, random_seed_a, random_seed_b; 
    std::ifstream file ("/dev/urandom", std::ios::binary);
    if (file.is_open())
    {
        char * memblock;
        int size = sizeof(int);
        memblock = new char [size];
        file.read (memblock, size);
        file.close();
        random_seed_a = *reinterpret_cast<int*>(memblock);
        delete[] memblock;
    }// end if
    else
    {
        random_seed_a = 0;
    }
    random_seed_b = std::time(0);
    random_seed = random_seed_a xor random_seed_b;
    std::cout << "random_seed_a = " << random_seed_a << std::endl;
    std::cout << "random_seed_b = " << random_seed_b << std::endl;
    std::cout << " random_seed =  " << random_seed << std::endl;
    return random_seed;
} // end good_seed()
于 2010-04-14T23:42:42.120 に答える
1

従来、最初または2番目のユーザー入力を使用して値をシードしていました。これは、応答にかかる時間(チックからミリ秒の範囲)がかなり変動するためです。

于 2010-04-14T20:22:47.100 に答える
1

多分あなたはよりも好むべき/dev/urandom/です/dev/random。十分なエントロピーが利用できない場合、後者は Linux でブロックされます。これは、プログラムがユーザーの操作なしでマシン上で実行されている場合に簡単に発生する可能性があります。を開けない場合は/dev/urandom、フォールバックを使用する代わりに例外をスローできます。

于 2010-04-14T21:10:39.727 に答える
1

「良い」発電機、「悪い発電機」では何の意味もありません。「乱数を生成する算術的方法を考える人は、もちろん、罪の状態にあります。」-ジョン・フォン・ノイマン。そのようなジェネレーターはすべて、単なる決定論的アルゴリズムです。十分なエントロピーをもたらす初期状態 (シード) を持つことが非常に重要です。必要なものに応じて、ジェネレーターの品質をテストする必要があります。モンテカルロ法は、疑似乱数発生器の非常に優れた推定器です。

于 2010-04-14T21:28:30.673 に答える
0

良いと定義する. :-)

シードをすばやく見つけることが重要ですか、それとも、まとめるのにどれだけ時間がかかっても、シードをできるだけランダムにすることが重要ですか?

バランスをとるために-間違いなく最もランダムではなく、間違いなく最速でもありません...

  • 最初に呼び出されたときに、システム時間をミリ秒単位で取得します。
  • SHA-1 などのハッシュ関数を使用して実行します。
  • 結果をシードとして使用します。

これにより、ほぼランダムな 160 ビットが得られます。これは、10^50 程度の変動性です。ハッシュの実行には数秒かかるため、これは電光石火の速さではありませんが、これまではバランスが取れていました。

于 2010-04-14T20:19:36.163 に答える