19

単一の乱数ジェネレーター (RNG) を使用して複数の数値を生成することと、ジェネレーターごとに 1 つの数値を生成して破棄することに違いはありますか? 両方の実装で同じようにランダムな数値が生成されますか? これについて、通常の RNG と安全な RNG の間に違いはありますか?

クライアントに代わって乱数のリストを生成することになっている Web アプリケーションがあります。つまり、数字は各クライアントの観点からランダムに見える必要があります。これは、クライアント セッションごとに個別のランダム RNG を保持する必要があるということですか? または、すべてのセッションで 1 つの RNG を共有できますか? または、リクエストごとに RNG を作成して破棄できますか?

更新: この質問は、ランダム シーケンスのサブセットもランダムですか? に関連しています。

4

10 に答える 10

22

乱数ジェネレーターには状態があります。これは実際には必要な機能です。次の「乱数」は、前の数とシード/状態の関数です。純粋主義者はそれらを疑似乱数ジェネレーターと呼んでいます。数値はランダム性の統計テストに合格しますが、実際にはランダムではありません。

ランダム値のシーケンスは有限であり、繰り返されます。

乱数ジェネレーターは、数値のコレクションをシャッフルし、ランダムな順序で処理するものと考えてください。シードは、数値を「シャッフル」するために使用されます。シードが設定されると、数字のシーケンスが固定され、予測が非常に難しくなります。一部のシードは、他のシードよりも早く繰り返されます。

ほとんどのジェネレーターには、誰もそれが繰り返されていることに気付かないほど長い期間があります。48ビットの乱数ジェネレーターは、繰り返す前に数千億の乱数を生成します-(AFAIK)32ビットのシード値を使用します。

ジェネレーターは、単一のシードを与えて値を吐き出させた場合にのみ、ランダムに似た値を生成します。シードを変更すると、新しいシード値で生成された数字は、以前のシードで生成された値と比較するとランダムに表示されない場合があります。シードを変更すると、すべての賭けがオフになります。だからしないでください。

健全なアプローチは、1 つのジェネレーターを使用して、さまざまなクライアントに数値を「処理」することです。ジェネレーターの作成と破棄をいじらないでください。種子の交換を台無しにしないでください。

とりわけ、独自の乱数ジェネレーターを作成しようとしないでください。ほとんどの言語ライブラリに組み込まれているジェネレータは非常に優れています。特に 32 ビット以上を使用する最新のもの。

一部の Linux ディストリビューションには/dev/randomand/dev/urandomデバイスがあります。これらを一度読み取って、アプリケーションの乱数ジェネレーターをシードできます。これらは多かれ少なかれランダムな値を持ちますが、ランダムなシステム イベントから「ノイズを収集」することによって機能します。使用の間に多くのランダムなイベントが発生するように、慎重に使用してください。

于 2008-10-15T03:37:39.650 に答える
12

単一のジェネレーターを複数回使用することをお勧めします。私の知る限り、すべてのジェネレーターには状態があります。ジェネレーターをシードするときは、シードに基づいてその状態を設定します。新しいシードを生成し続けると、選択したシードが、1 つのジェネレーターを使用して生成された数値ほどランダムでなくなる可能性があります。

これは、現在のミリ秒単位の時間をシードとして使用する、私が使用したほとんどのジェネレーターに特に当てはまります。

于 2008-10-15T01:04:52.033 に答える
11

ハードウェアベースの真の [1] 乱数ジェネレーターは可能ですが、自明ではなく、平均レートが低いことがよくあります。可用性も問題になる可能性があります [2]。「乱数発生器」と組み合わせて「ショットノイズ」または「放射性崩壊」をグーグルで検索すると、いくつかのヒットが返されるはずです。

これらのシステムは、状態を維持する必要はありません。おそらくあなたが探していたものではありません。

他の人が指摘したように、ソフトウェア システムは疑似乱数にすぎず、状態を維持する必要があります。

妥協案は、ハードウェア ベースの RNG を使用して、PRNG のシードに使用できるエントロピー プール (保存された状態) を提供することです。これは、/dev/random [3] および /dev/urandom [4] の Linux 実装で非常に明示的に行われます。

これらは、 /dev/random エントロピー プールへのデフォルトの入力が実際にどの程度ランダムであるかについての議論です。


脚注:

  1. 私たちの物理学の理解に問題がある場合はモジュロ
  2. ランダムなプロセスを待っているからです
  3. /dev/random 機能は、実際またはほぼランダムであると考えられるさまざまなソースからシードされたエントロピー プールに直接アクセスし、エントロピーが使い果たされるとブロックします
  4. /dev/urandom は /dev/random に似ていますが、エントピーが使い果たされると、エントロピー プールを効果的にステートフルな PRNG にする暗号ハッシュが採用されます。
于 2008-10-15T15:30:51.207 に答える
5

RNG を作成し、そこから 1 つの乱数を生成してから RNG を破棄すると、生成される数は、RNG の開始に使用されたシードと同じくらいランダムになります。

単一の RNG を作成し、そこから多くの数値を引き出す方がはるかに優れています。

于 2008-10-15T01:06:57.783 に答える
2

人々がすでに言ったように、PRNG を一度シードして再利用する方がはるかに優れています。安全な PRNG は、暗号化アプリケーションに適した単純な PRNG です。毎回再シードすることで合理的にランダムな結果が得られる唯一の方法は、それが真にランダムな「現実世界」のソース、つまり特殊なハードウェアに由来する場合です。それでも、ソースが偏っている可能性があり、理論的には同じ PRNG を使用する方が良いでしょう。

于 2008-10-15T01:21:12.653 に答える
2

通常、深刻な PRNG の場合、新しい状態のシードにはかなりの時間がかかり、毎回新しい状態を作成してもあまり役に立ちません。複数の PRNG が必要になる唯一のケースは、システムが異なる場合です。たとえば、カジノ ゲームでは、カードをシャッフルするためのジェネレータが 1 つと、コンピュータ制御キャラクターによって行われるコメントを生成するためのジェネレータが 1 つあるとします。ユーザーは、キャラクターの行動に基づいて結果を推測することはできません。

シードの良い解決策は、これ (Random.org)を使用することです。これらは、大気ノイズから生成された乱数を無料で提供します。時間を使うよりも、種をまくのに適したソースになる可能性があります。

編集:あなたの場合、優れたプログラミング標準以外の理由がなければ、クライアントごとに1つのPRNGを確実に使用します。とにかく、クライアント間で 1 つの PRNG を共有する場合でも、PRNG の品質と等しい品質の疑似ランダム値をそれぞれに提供することになります。それは実行可能なオプションですが、プログラミングの悪い方針のようです

于 2008-10-15T01:32:06.173 に答える
1

Haskell は可変状態を完全に排除しようとする言語であることは言及する価値があります。この目標を IO のような厳しい要件 (何らかの形式の可変性を必要とする) と調和させるために、モナドを使用して、ある計算から次の計算に状態をスレッド化する必要があります。このようにして、Haskell は疑似乱数ジェネレーターを実装します。厳密に言えば、乱数の生成は本質的にステートフルな操作ですが、Haskell は状態「ミューテーション」を bind( >>=) 操作に移動することでこの事実を隠すことができます。

これはおそらく少し抽象的に聞こえますが、あなたの質問に完全に答えるわけではありませんが、それでも適用できると思います。理論的な観点からは、状態を伴わずに RNG を操作することは不可能です。とにかく、この相互作用を軽減し、操作全体がステートレスな性質のものであるかのように見せるために使用できる手法があります。

于 2008-10-15T06:00:14.230 に答える
0

安全な PRNG の使用は、アプリケーションによって異なります。乱数は何に使用されますか? それらが本当に価値のあるもの (たとえば、暗号に関連するもの) である場合、それ以下のものは使用したくないでしょう。

安全なPRNGははるかに遅く、任意の精度の操作や素数テストなどを行うためにライブラリが必要になる場合があります...

于 2009-01-22T00:39:36.027 に答える
0

通常は、単一の PRNG を作成し、そこから複数の値を取得することをお勧めします。複数のインスタンスを作成するということは、インスタンスのシードが一意であることを保証する必要があることを意味します。これには、インスタンス固有の情報を組み込む必要があります。

余談ですが、より優れた「真の」乱数ジェネレーターがありますが、通常、コンピューター内の電気信号の分散からランダムデータを導出するなどの特殊なハードウェアが必要です。本当に心配していない限り、シード値が簡単に予測できない限り、言語ライブラリや OS に組み込まれている疑似乱数ジェネレーターでおそらく十分だと思います。

于 2008-10-15T01:14:24.947 に答える
-2

まあ、それらが作成されるたびに異なる方法でシードされる限り、いいえ、違いはないと思います。ただし、時間などに依存する場合は、シードが偏っているため、おそらく不均一になります。

于 2008-10-15T01:04:42.767 に答える