システム開発運用のKIです。

皆さん「乱数」って使いますか?

 

ゲームプログラミングであれば使う機会は多数考えられますが、
一般的な業務システムでは使う機会は少ないのではないでしょうか。

私が過去に業務システム内で触れたのは
1.特定の条件に基づいて並び替え
2.全ての条件を使っても並び順が決定できない場合、乱数で順序を決める
といったものでした。

 

ゲーム以外で触れる機会で考えると
音楽プレイヤーのランダム再生
当たり付き自動販売機
抽選で○○人に合計△△万円キャッシュバック!
とかでしょうか。
まともな乱数は音楽プレイヤーだけで、他は何らかの調整がある気がしますが
そこは一旦気にしないことにしましょう。

 


コンピューター上で扱う乱数はなかなか奥深いものです。
「1~6の範囲で整数値の乱数を作る」場合、
人間であればサイコロを振るだけで良いです。

ですが、コンピューターにはそれができません。
本当に機械的にサイコロを投げるような、ハードウェア乱数生成器と呼ばれる機械も存在しますが、
全てのコンピューターに組み込むことはできません。
なので「疑似乱数」と呼ばれるものが使用されます。
線形合成法や逆関数法、ボックス・ミュラー法といった、名前だけで頭の痛くなる計算式で算出されています。
ではなぜそんな複雑な計算方法で乱数を作成する必要があるのでしょうか。

 


例えば以下の数列

857142857142857

ランダムな数字の羅列に見えますか?

実はこれは「記事の下書きを7月13日に書いているから 13 / 7 = 1.857142857142857
この小数点以下の部分です。
1月や7月14日には使えない欠陥計算式ですが
7月15日や16日にはどのような数字が並ぶか、簡単に予想ができてしまいます。
結果が予想できてしまう数値は乱数とは言えません。

 

書いていて思い出しました。
かつてプレイステーション2で発売されたゲーム、真・三国無双4で、「時刻法」と呼ばれる攻略情報がありました。
簡単に説明すると
「ゲーム機本体の時計を特定の日時にセットすることで、確定でゲーム内レアアイテムが手に入る」というものです。
ゲーム内乱数が「ゲーム機本体の時計」に依存する、ということが発覚したために編み出された手法です。

 

ゲームなのでまだ良かったですが、これがもし
『抽選で○○人に合計△△万円キャッシュバック!』で使用できてしまうとどうなるでしょうか。
「○時○分に決済ボタンを押すと高確率でキャッシュバックが当たる」なんてことになると……考えたくないですね。

 

また、このような「予想できる乱数もどき」はセキュリティ上も問題になります。
乱数は暗号化技術でも使用されています。

 

シーザー暗号で簡単な例を出してみます。
シーザー暗号は元となる単語(平文)を特定の文字数だけシフトすることで暗号化します。

 

平文:HELLO
これを1文字ずつ後ろにずらすことで
結果:IFMMP
となります。

 

全部1文字ずつずらすだけでは簡単すぎるので、ずらす量を1文字ずつランダムに変更します。
ずらす量を
1文字目:8
2文字目:5
3文字目:7
4文字目:1
5文字目:4
としてみます。

 

こうすると
平文:HELLO
結果:PJSMS
となります。

 

大分暗号っぽくなりました。
しかし、ここで使用した「85714」
これは何の値か?というと、そう、乱数ではなく「13 / 7 = 1.85714」です。
暗号っぽくなっていても、結局これでは容易に解読されてしまいます。

 


このような理由から、上記の頭が痛くなる計算法を使用し、
予想が困難な方法で疑似乱数を生成しています。

 


・乱数を作るのは簡単そうで結構大変
・乱数に見えても実は疑似乱数、だけどほぼ乱数
・すごくややこしい計算が行われた結果、スマホに「ざんねん」の文字が表示されている

 

そんな話でした。