1. ホーム
  2. c++

[解決済み] Reinventing The Wheel(車輪の再発明)。乱数発生器

2022-03-07 14:16:04

質問

私はC++の初心者で、いろいろと勉強しているところです。そのため、私は乱数発生器(RNGまたはPRNG)を作ろうとしています。RNGの基本的な知識は持っています。例えば、シードから始めて、そのシードをアルゴリズムに通して送らなければなりません。私が困っているのは、人々がどのようにそのアルゴリズムを考え出すかということです。

以下は、私がシードを取得するために持っているコードです。

int getSeed()
{
    time_t randSeed;
    randSeed = time(NULL);
    return randSeed;
}

C++で作られたRNGがあることは知っていますが、ただ他の人の仕事をコピーして理解しようとするのではなく、学びたいと考えています。

そこで、もしどなたかこのようなアルゴリズムの読み方や例を教えてくださる方がいらっしゃれば、大変ありがたいです。

どのように解決するのですか?

最初にはっきりさせておきたいのは、あなたが考え出したアルゴリズムは疑似乱数発生器であって、真の乱数発生器ではないということです。 アルゴリズムを作る(つまり関数を書く、つまりルールを作る)ことになるので、乱数発生器は最終的に自分自身を繰り返すか、似たようなことをしなければならず、非乱数になってしまいます。

真の乱数発生器の例としては、自然界のランダムなノイズを取り込み、それをデジタル化したものがある。 例えば、以下のようなものがある。

http://www.fourmilab.ch/hotbits/

http://www.random.org/

また、ホワイトノイズ(またはランダム性に関する他の手段)を発生させる物理的な装置を購入し、それをデジタルでキャプチャすることも可能です。

http://www.lavarnd.org/

http://www.idquantique.com/true-random-number-generator/products-overview.html

http://www.araneus.fi/products-alea-eng.html

疑似乱数生成器について、最も習得しやすいもの(平均的な素人でも自作できるもの)は 線形合同発電機 . 残念ながら、これらは最悪のPRNGの一つでもあります。

良いPRNGを判断するためのガイドラインとしては、以下のようなものがあります。

  1. 周期性(使用可能な数値の範囲は?)
  2. 連続する数字(同じ数字が2回連続で繰り返される確率は?)
  3. 均一性(ある部分範囲から数字を選ぶのと、別の部分範囲から選ぶのは同じ確率か)
  4. リバースエンジニアリングの難しさ(もし本当にランダムに近いのであれば、誰かが最後に生成した数個の数字から次に生成する数字を割り出すことはできないはずです。)
  5. 速度(新しい数字を生成する速度は?5回なのか500回の算術演算なのか?)
  6. 他にも見落としがあるはずです。

ほとんどの用途で(つまりcrptographyではない)良いとされている、今人気のあるものの1つが、以下のものです。 メルセンヌ・ツイスター . リンク先にあるように、おそらく30行程度のコードしかないシンプルなアルゴリズムです。 しかし、その20行や30行のコードをゼロから考え出そうとすると、多くの頭脳とPRNGの勉強が必要になります。 通常、最も有名なアルゴリズムは、PRNGを何十年も研究してきた教授や業界の専門家によって設計されています。

PRNGを勉強して自分で作ってみてほしいのですが(KnuthのArt of Computer ProgrammingやNumerical Recipesが出発点です)、結局のところ(PRNGがライフワークにならない限り)誰かが考え出したものを使うほうがずっといい、ということを整理しておきたいと思います。 もしあなたが高品質のPRNGを必要とするならば、C++、Excel、.NET、Javaなどの標準ライブラリのものを、彼らが何を使って実装しているかを調査するまでは使わないでください。