web-dev-qa-db-ja.com

乱数ジェネレータはどのように機能しますか?

私はphp Rand()関数について考えていて、それをどのように再作成できるかを考えていたところ、完全に困惑しました。

乱数ジェネレータはどのように機能しますか?

24
Korvin Szanto

乱数ジェネレータ(RNG)は、実際にはTRULY乱数を生成することが不可能であるため、実際には疑似乱数を生成しています。本当に本当にランダムなものは、雷のような神の行為だけです。

このウィキペディアの記事は、説明であなたを助けることができるかもしれません: http://en.wikipedia.org/wiki/Random_number_generators


私が理解していることから、RNGには基本的に2つの部分があります。シードと、そのシードから選択された乱数です。 RNGをシードすると、それは開始点と同等になります。その開始点には、プログラムが選択する「内部」にある多数の数値があります。 PHPでは、srand()を使用してシードを「シャッフル」できるため、ほとんどの場合、別の答えが返されます。次に、Rand(min、max)を使用してシードに移動し、最小値と最大値の間の数値を選択できます。


警告、可能性のある安っぽいアナロジーが先にあります!

それぞれの「種子」をアイスチェストと考え、次に乱数をアイスキューブと考えます。たとえば、1000個のアイスチェストがあり、各チェストに1000個のアイスキューブが入っているとします。郡の見本市では、アイスチェストを選択して飲み物を使い始めます。アイスキューブは1つしか使用できません。ただし、必要なのは1立方インチより大きい氷だけです。つまり、1000個のチェストの中からランダムにチェストを選択し、次にチェスト内のアイスキューブをランダムに選択します。彼らが望むサイズでうまくいくなら、彼らはそれを使います。そうでない場合は、他の人と一緒に胸に戻します。もう少し楽しくしたい場合は、事前にチェストを交換して完全に気づかれないようにします。

PHPが実際にシードと乱数を実際に選択する方法については、そのことについて十分な知識がありません(おそらく、あなたが最も疑問に思っていることです!)。 Rand()関数を試してやり直してください。作成するほとんどのWebベースのアプリケーションでは、Rand()は必要な乱数に十分対応できます。

また、線形合同ジェネレーターも確認してください。これは、詳細な情報が必要な場合に探しているものの詳細になる場合があります。 http://en.wikipedia.org/wiki/Linear_congruential_generator

お役に立てれば!

7
Mr. Starburst

通常は真にランダムではありませんが、ランダムに見える数列を生成するため、疑似ランダムと呼ばれます。これは、いくつかの興味深い数式で行われます。最も一般的なものの1つは Linear Congruential Generator です。

疑似乱数には、真の乱数にはない便利なプロパティが1つあります。起動時に同じシードを使用すると、同じシーケンスが返されます。これはテストに非常に便利です。

18
Mark Ransom

疑似ランダムまたはランダムを求めていますか?他のものは疑似ランダムについて答えました、ランダムについて話させてください。

実際にハードウェアベースの乱数ジェネレータが販売されていました(ありますか?)。それらは、深宇宙放射線のホワイトノイズを測定する小さなラジオ、または小さな放射性サンプルとその崩壊の間の測定期間を備えたチップに基づいていました。それらの問題は帯域幅でした-それらが生成できるエントロピーの量はそれほど多くなかったため、疑似ランダムアルゴリズムのシードに使用されました。それらは銀行システム、高セキュリティなどで使用されていました。

OTOH、組込みシステム開発者に会ったら、彼らは笑います。マイクロコントローラーのプログラミングの一般的な目的で、フローティング(接続されていない)ピンを使用して16ビットアナログデジタルコンバーターの下位4ビットを読み取ると、十分な帯域幅以上で完全に良好なランダムノイズが生成されます(ポーリング周期が短いほど、 "ノイズが多い」読み出し)、実際のRNGルーチンを記述するよりも簡単です。また、ADCがマイクロコントローラーのシリコンに実装されていることが一般的であり、多くの場合、アプリケーションに5チャネルが必要な8チャネルで実装されていることを考えると、実際には無料です。

また、ADCがない場合でも、デジタルGPIOピンに接続されたいくつかの要素はかなり良いノイズを生成します。組み込みでは、ノイズは常に存在します(そして常に争われます)。そのため、真のランダム性を取得することは非常に簡単です。

4
SF.

数値の「ランダムな」シーケンスをエミュレートすることを試みる多くの方法があります。最初にやるべきことは、確かに linear congruential generators について読むことです。これが最も基本的な乱数発生器の動作方法であり、PHPのRand()関数の動作方法だと思います。

熟考するためのより興味深い次の質問は、それがどのようにそれ自体を種にするのですか?時間? IPアドレス?等.

2
Sean Owen

まず、事実上すべてのRand()関数は真のランダム性を提供せず、いわゆる疑似乱数を提供します。

それでは、疑似乱数ジェネレータはどのように機能するのでしょうか?基本的には暗号化と同じように機能します。ある入力を受け取り、複雑な方法で出力を生成する関数(ハッシュ)があり、出力から入力を推測すること、またはその逆が不可能です。つまり、すべての暗号を使用して、かなり良い疑似ランダムジェネレーターを作成できます。ただし、任意の疑似乱数ジェネレーターを使用して暗号化を行うことは原則として可能ですが、ほとんどの疑似乱数ジェネレーターは主に暗号化セキュリティではなく速度を目的として開発されているため、ハッカーに頭痛の種を与えることはありません。

疑似ランダムジェネレーターの場合、ハッシュ関数はジェネレーターの非表示の内部状態に適用され、その出力は、a)その内部状態を変更するため、およびb)Rand()の出力を計算するために使用されます。関数。 Rand()の次の呼び出しは、変更された内部状態を使用するため、異なる結果が生成されます。ハッシュ関数が優れているほど、結果が真の乱数と区別しにくくなります。


実際のところ、コンピュータは現在、実際の乱数にアクセスしています。これらは、外部デバイスによって生成される割り込みのタイミングのジッターに起因しています。 Linuxは、これらの小さな不確実性の値を使用して、数キロバイトの内部状態である「エントロピープール」を常に攪拌します。このエントロピープールに基づく暗号化ハッシュは、/dev/randomおよび/dev/urandomデバイス。したがって、いくつかの本当に良い乱数へのアクセスは、これら2つのデバイスの1つを開き、それらからいくつかのバイトを読み取るのと同じくらい簡単です。