一般的に応用されているオープン(未接続)ADポートを使った乱数の品質を測定してみました。
乱数評価の指標としてFIPSなど規格はありますけれども、もっと具体的に「クラスに同じ誕生日の人がいる確率」のような例として例えば、DALIなどの24bit固有IDにADの乱数を使用した場合の性能としてネットワークに接続された台数に応じてどれくらいの確率でアドレスが一致か(ぶつかるか)をAD変換時間による変化を見てみました。
↓の結果から一番性能がいい設定(変換時間=38usec)でも30台を超えると50%の確率でアドレスの衝突が発生するようです。真性乱数に比べると有効ビットが半分程度になるみたいですね。
温度や外来ノイズ?など同じ設定でも測定するたびに一致確率が10%20%くらい大きくバラつきますけど、 概ね変換時間が長い方が性能が良くなる傾向があるようです。
ちなみに真性乱数の場合、乱数ビットvs一致確率を見てみると乱数ビットが20ビットを超えてくるとほぼ衝突することはないようです。 (左の標準と右のログ表示で比べ見るとわかりやすいかな。)
ちなみに真性乱数とAD乱数を比較すると、だいたいAD乱数24ビットが真性乱数9か10ビット程度の性能になるようです。 ↓ AD乱数(38usec)は真性乱数9ビットと10ビットの間くらいですからね。
遂にAD乱数が真性乱数になりました。
AD変換の周期を伸ばしていき、概ね500usec周期でAD変換することで真性乱数の分布に近づいていきます。 500usecを超えたら10msec周期でも乱数の品質は変わりません(一致確率が0.02%前後)。乱数の一致確率のバラつきは統計上の誤差範囲に入っています。
ただ1ビット生成するのに500usecとすると24ビット分生成するのに12msec掛かってしまいます。。。
↑上の分布はまさに↓下の1/fノイズの形になってますね。(ノイズが増えると乱数のバラつきが広がって真性乱数に近づく) 10KHz(=1/100usec)以下の周波数帯になるとCMOS起因のノイズが指数関数的に増えるのでA/D変換の周期が伸びるとある種HPFのカットオフが下がるためノイズをたくさん重畳していきます。
24bitの乱数を生成するのに12msecは掛かりすぎな気がするので別解として、パリティ方式を考えました。
空きポートのAD変換の下位1ビットをとってくるところは変わりませんけれども、下位1ビットを複数あつめて 例えば下位1ビットを6個分並べて、1が立っている個数が奇数なら1、偶数なら0として扱った場合(例えば"010110"なら"1"となる)これだけで真性乱数のできあがりです。
6ビット以上なら7ビットでも8ビットでも20ビットでもパリティを取れば(Nビット分を1ビットに圧縮した)乱数の品質は変わりません。 乱数1ビット生成するのに38usec×6ビットなので、24ビット長の真性乱数を生成する時間は5.5msec程度になります。
あるいは変換時間を2.3usecにしてパリティを取る長さを少し長めの20ビットにして、2.3usec×20×24=1.1msecあたりでもそれなりの乱数品質を得られそうです。このスレッドのグラフは変換時間38usecで測定してますけれど最初の投稿の結果では2.3usecでも38usecでも品質はほとんど(=倍半分程度しか)変わりませんでしたので。
RL78のA/Dポートでの乱数生成に手こずっているのは、ひとえにRL78のADの特性が良すぎるのが原因です。 :-P
まとめとしては、乱数の品質測定の1つの目安として DALIで代表される24ビットのユニークアドレスの衝突確率を実機で測ってみるのが分かりやすいと思います。 24ビットの乱数を64個生成し、64個の中で乱数値が一致するかを10000回検査して以下の式から一致確率を求めれば乱数の品質が簡単に分かります。 一致確率 = (一致が発生した回数/10000回) 真性乱数なら0.012%前後(10000回中0~6回)に収まります。
最終的には適用するシステムの要求によって乱数生成に使える時間的制約と乱数品質のトレードオフになるかと思います。
PS 2018/2/14 以下数値を訂正します× 真性乱数なら0.02%前後 ○ 真性乱数なら0.012%前後
IKUZOさん
IKUZOさんのおっしゃるように複数要素を組み合わせて乱数を作る方法もありますよね。 ただ、個別の要素毎に品質を確認した上で組み合わせないと、トータルの品質を規定できないので A/Dを使った場合の実力、2つのタイマーを使った実力、未初期化RAMを使った実力、などをそれぞれ確認していきたいと思っています。
今のところ、RTCを使った方法は1ビットあたり1msec以上の周期であれば真性乱数に、(詳細は「RL78で真性乱数生成器(TRNG)」) A/Dも複数回分のパリティを取れば1ビットあたり200usec以上の周期で真性乱数になることが分かりました。
A/Dの端子処理はハイインピーダンスにしないとノイズが乗らないのでANI2をオープンにして使っています。そういう意味で、A/Dポートは「未使用」ではなく乱数生成用に使用しているので未使用端子処理は不要です。
ランダム関数は、乱数自体を研究されている方が日本で100人くらいいて、数式(アルゴリズム)による擬似乱数を極めて、真性乱数に匹敵する性能を出しています。 一方で、ハードを使った乱数は扱い方さえ適切なら、あまり数学に明るくない私達でも簡単に品質の高い乱数を作れるかなと思います!