完全な乱数
2025.03.16
完全な乱数なんて有るのでしょうか?
たとえばMSX-BASICなどには乱数があります。これで簡単に乱数が得られると思うでしょう。
ところが、これは疑似乱数、算術乱数と呼ばれるものです。規則性を持っている、予想できるという意味で、完全な乱数ではありません。
MSX-BASICの内部は知りませんが、一般的な乱数ルーチンでは(簡単な例で)もとの数を5倍して+1する、といった具合に乱数を得ていますから、次の乱数が予想できるわけです。
シミュレーションの再現性という意味では、かえってそのほうが都合の良い場合もあるかもしれません。
インターバルタイマー(例えば1/60)で内部的にカウンタを回しておき、RND関数を呼び出した瞬間の値を拾ってそれを利用するとか。
中学生の頃、BASICでサイコロの確率のシミュレーションを行いました。サイコロを転がす回数が増えれば増えるほど1/6に近づいていきました。
学生の頃に友人がMSX上でSEGAのアーケード機のTETRISを再現しました。その時に、乱数について議論したのでした。
テトリミノは7種類あって、一方で我々が使っている乱数は2進数をベースにしているから、3bitだと0~7の値をとるから8種類、ひとつ余る。
0~6を(NEXTの)テトリミノに割り当てたとして、7が出た時は0~6が出るまで乱数の発生をやり直すか?
その場合の確率的には偏りがあるのか?
7が続けて何度も出るのではないか?
・・・などと議論しました。
そもそもSEGAのTETRISは乱数でNEXTを決めているのかどうかは知りません。我々は、おそらく乱数だろうと考えて作りました。根本的な部分です。
実際、棒ばかり続けて出る事もあったと思います。(あえてデバッグの為に、棒だけ出るようにして試した事もありました。全消しをするとボーナス点になるか確認するなど)
脱線しましたが、乱数を発生するサブルーチンは「Z80マシン語秘伝の書」に載っていたものを利用しました。結局、計算によって次の乱数を求めているので、完全にランダムとは言えないと思います。
その上で、さらに別の乱数を組み合わせて・・・などと考えたりもしましたが、結局どこかで規則性をもってしまいます。
もうひとつ別の乱数ルーチンがあって、その数字と足したり掛けたりして真ん中の1桁を取り出して・・・などと複雑にやっても、やはり規則性があるのです。
円周率をそのまま乱数列として使う、という案も聞いたことがあります。それはメモリ容量を食います。今の時代では問題にならないかも。
理想を求めれば物理乱数になりますが、さすがにCPUだけでは発生できません(発生機能を持っているCPUもあるかも。ここではZ80での話なので発生機能なし)。
古典的な手法では、ノイズ発生機を用いて作ります。そのノイズも、外乱の影響を受けないようにしたものでなければなりません。
Arduinoでは空きピンのアナログポートを読んで、その不定値を乱数あるいは乱数の種にするというのがありました。
パチンコやパチスロの乱数というか抽選は、高速で回るカウンタが有り、たとえばスタートレバーを叩いた瞬間にその値を取ることで得ています。たとえば7だったら当たりとか、いくつからいくつまでの範囲ならベルとか、リプレイとか決まっていました。
昔はその速度が体感器で対応できる程度の遅さだったので、当たりのタイミングを狙う事ができました。その対策として現在ではさらに高速で回しているようです。
そのカウンタだって昔は独立したIC(74HC590等)でしたから、不正に細工をして当たる仕組みなんかもありました。
見た目は普通だけれど、プレイしてみるとおかしいというのでICをはずしてみたら、その裏側をほじくって、8ピンPICマイコンが貼り付いていたりとか。こいつがカウンタを操作して当たらせていたわけです。
昔、ある装置の電源を入れるたびにランダムな値を得たいという要望がありました。
これもずいぶん悩みました。たとえば、電解コンデンサの充放電時間のばらつきを利用しようとしました。誤差が大きいだろうと予想したものの、それほど大きくはありませんでした。
他社製品ではバックアップRAMによって前回の値を覚えていて、それを乱数の種にしていたようです。(やはり計算で乱数を求めていたのでしょう。そのためには乱数の種が必要)
前回値無しで毎回ランダムというのは、簡単そうに思えるけど実際は難しいです。
じつはこれも体感器対策のひとつでした。遊技機の電源は開店前、同時に入れられるので全台同期します。従って、隣の台に移動しても体感器が使えてしまいます。
そこで、タイマーを使って電源ONのタイミングを秒単位でずらしていました。ブレーカーをONにしても、それぞれバラバラに入ります。
だけど毎回のずらし時間は固定されているし、1台ごとにタイマーを入れるにはコストがかかりますから数台まとめて同時にONしていました。(トランスは遊技機4台に1台といった割当なのでトランス1台ごとのタイマー)
そこで1台ずつランダムにずらして電源ONできないか、という話になりました。その後に抽選方式が変わったので、こういったものは不要になりました。
たとえばMSX-BASICなどには乱数があります。これで簡単に乱数が得られると思うでしょう。
ところが、これは疑似乱数、算術乱数と呼ばれるものです。規則性を持っている、予想できるという意味で、完全な乱数ではありません。
MSX-BASICの内部は知りませんが、一般的な乱数ルーチンでは(簡単な例で)もとの数を5倍して+1する、といった具合に乱数を得ていますから、次の乱数が予想できるわけです。
シミュレーションの再現性という意味では、かえってそのほうが都合の良い場合もあるかもしれません。
インターバルタイマー(例えば1/60)で内部的にカウンタを回しておき、RND関数を呼び出した瞬間の値を拾ってそれを利用するとか。
中学生の頃、BASICでサイコロの確率のシミュレーションを行いました。サイコロを転がす回数が増えれば増えるほど1/6に近づいていきました。
学生の頃に友人がMSX上でSEGAのアーケード機のTETRISを再現しました。その時に、乱数について議論したのでした。
テトリミノは7種類あって、一方で我々が使っている乱数は2進数をベースにしているから、3bitだと0~7の値をとるから8種類、ひとつ余る。
0~6を(NEXTの)テトリミノに割り当てたとして、7が出た時は0~6が出るまで乱数の発生をやり直すか?
その場合の確率的には偏りがあるのか?
7が続けて何度も出るのではないか?
・・・などと議論しました。
そもそもSEGAのTETRISは乱数でNEXTを決めているのかどうかは知りません。我々は、おそらく乱数だろうと考えて作りました。根本的な部分です。
実際、棒ばかり続けて出る事もあったと思います。(あえてデバッグの為に、棒だけ出るようにして試した事もありました。全消しをするとボーナス点になるか確認するなど)
脱線しましたが、乱数を発生するサブルーチンは「Z80マシン語秘伝の書」に載っていたものを利用しました。結局、計算によって次の乱数を求めているので、完全にランダムとは言えないと思います。
その上で、さらに別の乱数を組み合わせて・・・などと考えたりもしましたが、結局どこかで規則性をもってしまいます。
もうひとつ別の乱数ルーチンがあって、その数字と足したり掛けたりして真ん中の1桁を取り出して・・・などと複雑にやっても、やはり規則性があるのです。
円周率をそのまま乱数列として使う、という案も聞いたことがあります。それはメモリ容量を食います。今の時代では問題にならないかも。
理想を求めれば物理乱数になりますが、さすがにCPUだけでは発生できません(発生機能を持っているCPUもあるかも。ここではZ80での話なので発生機能なし)。
古典的な手法では、ノイズ発生機を用いて作ります。そのノイズも、外乱の影響を受けないようにしたものでなければなりません。
Arduinoでは空きピンのアナログポートを読んで、その不定値を乱数あるいは乱数の種にするというのがありました。
パチンコやパチスロの乱数というか抽選は、高速で回るカウンタが有り、たとえばスタートレバーを叩いた瞬間にその値を取ることで得ています。たとえば7だったら当たりとか、いくつからいくつまでの範囲ならベルとか、リプレイとか決まっていました。
昔はその速度が体感器で対応できる程度の遅さだったので、当たりのタイミングを狙う事ができました。その対策として現在ではさらに高速で回しているようです。
そのカウンタだって昔は独立したIC(74HC590等)でしたから、不正に細工をして当たる仕組みなんかもありました。
見た目は普通だけれど、プレイしてみるとおかしいというのでICをはずしてみたら、その裏側をほじくって、8ピンPICマイコンが貼り付いていたりとか。こいつがカウンタを操作して当たらせていたわけです。
昔、ある装置の電源を入れるたびにランダムな値を得たいという要望がありました。
これもずいぶん悩みました。たとえば、電解コンデンサの充放電時間のばらつきを利用しようとしました。誤差が大きいだろうと予想したものの、それほど大きくはありませんでした。
他社製品ではバックアップRAMによって前回の値を覚えていて、それを乱数の種にしていたようです。(やはり計算で乱数を求めていたのでしょう。そのためには乱数の種が必要)
前回値無しで毎回ランダムというのは、簡単そうに思えるけど実際は難しいです。
じつはこれも体感器対策のひとつでした。遊技機の電源は開店前、同時に入れられるので全台同期します。従って、隣の台に移動しても体感器が使えてしまいます。
そこで、タイマーを使って電源ONのタイミングを秒単位でずらしていました。ブレーカーをONにしても、それぞれバラバラに入ります。
だけど毎回のずらし時間は固定されているし、1台ごとにタイマーを入れるにはコストがかかりますから数台まとめて同時にONしていました。(トランスは遊技機4台に1台といった割当なのでトランス1台ごとのタイマー)
そこで1台ずつランダムにずらして電源ONできないか、という話になりました。その後に抽選方式が変わったので、こういったものは不要になりました。
トラックバックURL
トラックバック一覧
コメント一覧
コメント投稿