C++ でダイスロールによってランダムな値を生成する
コンピューターは数字を推測できません。マシンがランダムな数値を生成するたびに、それはビット単位の操作の結果であるか、数値係数、つまり時間、シーケンスの派生物のいずれかです。
上記の方法を使用する場合の問題は、十分な回数繰り返すと同じ結果セットが生成されることです。
これが、ランダムな数値を生成するために使用される従来のアルゴリズムが暗号化の実践に推奨されない理由です。結果は簡単に予測できます。
ランダム性を予測する場合、ダイスのローリングはかなり簡単な作業です。この記事では、読者はコンピューターのランダム性と、C++ を使用して単純なダイスロールからランダムな結果を取得する方法について学習します。
C++ でダイスロールによってランダムな番号を生成する
疑似ランダムジェネレータは、ランダムに見える数値を作成するマシンです。逆に、それらは完全に予測可能です。
これは、従来のランダム数ジェネレーターがシードの使用を採用しているためです。シードは、簡単に言えば、時間または数値コンポーネントに依存する注入関数です。
たとえば、f(x0)
と呼ばれる x(0)
に注入関数を繰り返し適用することにより、特定のシード x(0)
に対して生成される結果。fn(x0)
は fn とは異なります。 -1(x0)
または fn-1(x0)
。ここで、fn
は関数構造 n
回を表します。
言い換えれば、f(x)
には、以前のものとは実質的に無関係な大きな飛躍が含まれています。
C++ でダイスロールのランダム番号を作成するために時間を使用するシード
ほとんどの場合、生成されるシードは時間係数に依存します。これは、注入機能がクロックの現在の秒を因数分解することを意味します。
より良い方法でそれを理解するために例を見てみましょう。
unsigned main_seed;
main_seed = time(0);
srand(main_seed);
ここでは、符号なし変数 main_seed
が初期化されます。この変数は、現在の時刻を格納するために使用されます。srand()
は、シードから結果を生成する C++ 関数です。
シードが生成されると、rand()
関数をシードとして使用して、線形方程式を使用してランダムな値を生成できます。
最新の CPU が関与しない限り、特徴的なシードをフェッチするために時間係数を使用することは良い習慣のように思われるかもしれません。
ほとんどの場合、生成されるシードは時間係数に依存します。これは、注入機能がクロックの現在の秒を因数分解することを意味します。
時計は思ったほど速くないので、srand(time)
を 1 秒間に何度も使用すると、同じシードが複数回取得されます。結果として、生成されるランダムな数値のセットは類似したものになります。
そして、これは、特にブロック暗号化プログラムでは、(重大な)問題になる可能性があります。後者の場合、人々は、大気データなどの温度変化などのリアルタイムの物理的形容詞に基づいて、または最近では、量子ビットの測定に基づいて、たとえば偏光光子がどのように重ね合わされるかという要因に基づいて、まともな数のジェネレータを購入します。
C++ で任意の番号を使用してダイスロールのランダム番号を作成するシード
次の例は、数値を使用した疑似数値ジェネレーターを示しています。
static unsigned long int rand_num = 2;
int rand(void) // The ceiling limit is kept at 32767
{
rand_num = rand_num * 113546545 + 12345;
return (unsigned int)(rand_num / 65536) % 32768;
}
void srand(unsigned int main_seed) // seed is stored inside variable main_seed
{
rand_num = main_seed;
}
符号なし int 変数 rand_num
は値 2
で初期化されます。上記のプログラムには、rand
と srand
の 2つの方法があります。
rand
メソッドは、新しい番号を初期化された値に連結します。シードの上限が設定されているため、rand
の mod と上限は、上限よりも低い数値を返します。
このメソッドから返される最終結果は、unsignedint にタイプキャストされます。
メソッド srand()
は、rand_num
からシード変数 main_seed
に値を渡します。
上記の方法を使用することの欠点
ご覧のとおり、srand(time(0))
を実行するか、シードに任意の値を取得すると、シードに依存する rand()
に常に新しい数値が返されます。しかし、数百万を超えると、その数は繰り返されます。
シードは、どのランダム番号が順番に作成されるかを制御します。つまり、srand(1)
は、ほとんどの場合、rand()
への最初の呼び出しで同じ値を生成し、rand()
への 2 番目の呼び出しで同じ番号を生成します。
つまり、各 rand()
呼び出しの前に同じシードが再シードされた場合、出力は常に同じランダム番号になります。したがって、1 秒間に time(0)
を数回シードすると、再シード後にすべてのランダム番号が同じになります。
数サイクル後に繰り返す必要がありますが、srand
引数がパターンを定義します。C++rand
は、シードを知っているとハッカーが次の数を見積もるのに役立つため、暗号化には適していません。
C++ を使用してダイスロールと同様のランダム値を生成する
このプログラムは、時間生成されたシードを使用して、1〜6 の範囲のランダムな数値を生成します。
パッケージのインポート
このプログラムには、次の 3つのインポートパッケージが必要です。
iostream
cstdlib
- 時間関数および rand 操作用time
- 時間関数のヘッダーパッケージ
iostream
は、プログラムの入出力操作のためにインポートされます。もう 1つのパッケージ cstdlib
は、C++ プログラムの基本的な制御操作に使用されます。
3 番目のパッケージは、プログラムのシードの作成に使用される time
パッケージです。
C++ のダイロールに従って値を生成する
ダイには 6つの個別の値があります。プログラムの役割は、範囲内でランダムな自然数を生成することである必要があります。これは、後続のダイロールで繰り返される可能性がありますが、全体的な結果は純粋にランダムに見える必要があります。
結果を見つけるために 3つの変数が初期化されます。変数 floor
と ceiling
はダイの最小値と最大値を格納し、変数 outcome
はランダムな数値を見つけるために使用されます。
int outcome;
int l_limit = 1;
int h_limit = 6;
最終値は rand()
関数を使用して生成され、結果を上限と下限の範囲内に制限します。
outcome = rand() % (max - min + 1) + min;
最後に、変数 roll
が返されます。
int outcome;
int l_limit = 1; // floor or lower limit of a die
int h_limit = 6; // ceiling or higher limit of a die
outcome = rand() % (h_limit - l_limit + 1) + l_limit;
return outcome;
時間を使用してシードを生成し、結果を表示する
プログラムは、srand()
関数内で現在の時刻を取得し、それを rand()
関数に渡します。アプリケーションは、メソッド Droll()
の rand()
関数を使用して、規定された制限内の自然な数値を検索します。
srand(time(0));
シードが生成された後、Droll()
メソッドを呼び出し、結果を出力する必要があります。
従来、3つのダイロールは常に完全なセットと見なされていました。この手法を 3 回繰り返して、ランダム性を検証します。
Droll()
メソッドを for
ループ内に配置し、print
ステートメント内で 3 回呼び出す必要があります。最終結果は、ダイロールから生成された疑似乱数の 3X3 マトリックスです。
for (int i = 0; i < 3; i++) {
std::cout << Droll() << " ";
std::cout << Droll() << " ";
std::cout << Droll() << std::endl;
}
プログラム内にすべてをまとめて、結果を見てみましょう。
#include <cstdlib>
#include <iostream>
#include "time.h"
int Droll() {
int outcome;
int l_limit = 1; // floor or lower limit of a die
int h_limit = 6; // ceiling or higher limit of a die
outcome = rand() % (h_limit - l_limit + 1) + l_limit;
return outcome;
}
int main() {
srand(time(0));
for (int i = 0; i < 3; i++) {
std::cout << Droll() << " ";
std::cout << Droll() << " ";
std::cout << Droll() << std::endl;
}
}
出力:
3 1 2
6 1 3
4 5 4
--------------------------------
Process exited after 0.00784 seconds with return value 0
Press any key to continue . . .
まとめ
この記事では、疑似番号ジェネレータの基本について説明しました。読者は、ランダムな数を生成するためのさまざまな方法と、それらの長所と短所を見てきました。
C++ プログラムは、範囲内でランダムな数値がどのように生成されるか、およびコンピュータープログラムを使用してダイスロールを模倣する方法について概念を明確にするために提供されています。