C++で実装するミッドスクエア法(平方採中法)による擬似乱数・ハッシュ生成
概要
ミッドスクエア法(平方採中法)とは、擬似乱数を生成するための古典的な手法の一つです。この方法は数学者のジョン・フォン・ノイマンによって考案され、1949年に開催された学会で発表されました。
この手法の基本的な流れは次のとおりです。
- まず初期シード値(種となる値)を選び、その2乗を計算します。
- 次に、2乗した結果の中央部分からいくつかの桁を取り出し、その数字を新しいシード値として採用します。
具体例
例として、3456を初期シード値とした場合を見てみましょう。3456の2乗は11943936です。
- 中央の4桁「9439」を新しいシード値とします。9439の2乗は89094721です。
- さらに中央の4桁「0947」を新しいシード値とします。
- 以降も同様に、この手順を繰り返していきます。
アルゴリズム
1. 初期シード値を選ぶ 2. シード値の2乗を計算する 3. 前回の計算結果からn桁を取り出し、シード値を更新する
C++での実装例
以下のコードでは、現在の時刻情報をもとに初期シード値を動的に生成し、ミッドスクエア法を用いてハッシュ値(乱数)を求めています。
#include <iostream>
#include <ctime>
using namespace std;
long long getTime(){
time_t t = time(NULL);
struct tm *tm = localtime(&t);
long long x = (tm->tm_hour) * 50000000 + (tm->tm_min) * 100000 + (tm->tm_sec) * 5000 +
(tm->tm_mday) * 50 + (tm->tm_year);
return x;
}
long getHash(){
long long key = getTime();
key = key * key;
key = key / 10000;
key = key % 100000000;
return key;
}
int main(){
cout << "Random number: " << getHash() << endl;
return 0;
}出力結果
上記のプログラムをコンパイルして実行すると、次のような出力が得られます。
Random number: 10088419
なお、シード値が現在時刻から生成されているため、実行するタイミングによって出力される数値は変化します。
注意点
ミッドスクエア法は実装が非常に簡単で理解しやすい反面、選んだシード値によっては短い周期で同じ数列を繰り返したり、途中で0に収束してしまうといった弱点があります。そのため、暗号技術などの本格的な用途には適しておらず、学習目的や簡易的な処理に向いた手法といえます。
-
C++で二分木内の指定キーの次の右ノードを検索する方法
問題概要この問題では、二分木(Binary Tree)とキー値が与えられます。目的は、指定されたキーを持つノードの次の右ノードを見つけることです。二分木とは、各ノードが最大2つの子ノード(左の子と右の子)を持つ特殊なデータ構造で、データの格納や効率的な探索に広く活用されています。具体例で理解しよう入力key = 4出力5説明ノード4と同じレベルに位置し、その右隣にある要素は5です。したがって、答えは5となります。解決アプローチこの問題に対するシンプルな解決策は、幅優先探索(レベル順走査)を用いて二分木を走査することです。具体的には、以下の手順で処理を行います。キューを使用してレベル順にノードを
-
C++で配列内に存在するキーKの出現確率を求める方法
問題概要サイズ「n」の配列が与えられ、その配列内に指定された要素 k が存在する場合に、その出現確率を求めることが課題です。配列の要素数と等しい「n」まで配列全体を走査し、指定された要素(キー)「k」を検索します。要素が配列内に存在する場合はその確率を計算して返し、存在しない場合は 0 を出力します。入力arr[] = { 1, 2, 3, 4, 5, 6} K = 5出力配列におけるキー 5 の確率 : 0.166入力arr[] = { 1,2,3,4,5,6,7 } K = 8出力配列におけるキー 8 の確率 : 0考え方上記はサイズ 7 の配列とキー 2 を例とした説明です。この場合、配