ブログ「サイバー少年」

ブログ「サイバー少年」へようこそ!
小学六年生ごろからプログラミングを趣味にしている高校生のブログです。
勉強したことについての記事などを書いています。フリーソフトも制作、公開しています。
(当ブログについて詳しくは「ブログ概要紹介」を参照)

サイバー少年が作ったフリーソフトは「サイバー少年の作品展示場」へ

乱数の発生確率はだんだん均等になってゆく

乱数とは、なにが出るか分からない、めちゃくちゃな数のことですね。

例えば0から9と限定して乱数を発生させた場合、1が出る確率は何%でしょうか。

本来なら10%が望ましいはずです。

偏ってしまったら公平じゃありませんからね。


しかし、現実では偏ってしまうものです。

10回、乱数を発生させても、0から9まで一つずつ出るとは限りません。


しかし、10回のところを、100回とか、1000回、10000回などにすると、
だんだん発生回数(=発生確率)が均等になってゆくと言うのです…。


そこでプログラムで乱数を発生させて実証してみました。



はじめに断りがありますが、プログラムの場合は乱数ではなく疑似乱数です。

規則性が無いように見えるほど複雑な規則を持つ数になります。

コンピュータは絶対に規則的になってしまうのです。


さて、.NET FrameworkでのRandomクラスは、乱数を発生させる際、現在時刻を式に入れます。

現在時刻なんてプログラムを実行するたびに異なりますから、すごく乱数っぽくなります。

そのため乱数と同じと思っていただいて構いません。



と言う訳で、C#で書きました。

こういうのって一般的にC言語で書くんですよね…。
C言語が公用語みたいなもんです。
早くC覚えたい…。


.exe同梱のコードファイルはこちらからダウンロード

Sample.zip
http://yahoo.jp/box/Smce2W


任意の回数、0から9までの乱数を発生させて、各数値の発生した割合を表示するプログラムです。

ためしに100回、乱数を発生させてみます。

出力結果


0 … 13.00000%
1 … 8.00000%
2 … 7.00000%
3 … 14.00000%
4 … 7.00000%
5 … 16.00000%
6 … 11.00000%
7 … 9.00000%
8 … 9.00000%
9 … 6.00000%

誤差 … +6.00000%, -4.00000%


本来なら全て10%になるのが理想なのですが、かなりばらついています。

「誤差」の部分は、10%のところを最大でプラスに6%、マイナスに4%ずれてしまっている数があるという意味です。

プラス方向なんて6%も誤差がでてしまっています。

やはり100回じゃ足りないみたいですね。

と言う訳で1000回、いや、10000回でやってみます。

出力結果


0 … 9.25000%
1 … 9.88000%
2 … 9.73000%
3 … 9.65000%
4 … 10.28000%
5 … 9.79000%
6 … 10.57000%
7 … 10.60000%
8 … 10.64000%
9 … 9.61000%

誤差 … +0.64000%, -0.75000%



誤差が急激に縮まりました。
プラスもマイナスも1%以内に収まっています。

10000回やれば、かなり均等になるようです。
(乱数ですから、あくまでも大体です。)


では、さらに均等にするため、1億回、乱数を発生させてみます。

1億回とはえらい数ですが、パソコンにとっては意外とちょろいもので、
私のパソコンでは10秒そこらで処理できます。

出力結果


0 … 9.99965%
1 … 10.00308%
2 … 10.00064%
3 … 10.00351%
4 … 9.99741%
5 … 10.00153%
6 … 10.00071%
7 … 9.99838%
8 … 9.99839%
9 … 9.99672%

誤差 … +0.00351%, -0.00328%


もう、誤差は無いと言っていいほどですね。

つまり、理想である「全て10%」の状態に、とてつもなく近づいているのです。



何度も言いますが、乱数ですからやるたび結果は異なります。

10回、乱数を発生させてみたら、全部10%になったということもあると思います。
(完璧に全部10%になる確率は、乱数の発生回数が10回のときのほうが高いです。)


ただ、ご覧にいただいたとおり、乱数の発生回数が多いほど全部10%に近づいてゆきます。


私は乱数を語れるほど詳しくありませんが、
本来、乱数として出てくる数の出現確率は全て同じなんだと思います。

ただ、乱数を発生させる回数が少ないせいで、ばらつきが生じてしまうだけです。

ですから、無限回、乱数を発生させることができたなら、
それぞれの数の出現確率は全て同じになるんだと思います。


以上、実験付きの私の考えでした。



追伸

任意の回数、乱数を発生させるこのプログラムは、もともと
Monoと連携してAndroid上でC#のプログラムを入力、実行できるAndroidアプリ「C# To Go」で書いていたんですが、

タブレットPCの処理は遅いですね。

10000回の乱数の発生でも、だいぶ時間がかかりますし、

1000万回、乱数を発生させようとしたら、2分以上かかってタイムオーバーになりました。

「C# To Go」では、処理に2分以上かかっていると強制的に中断されるんです。


同じプログラムをパソコンで書いて、1000万回でやってみると2秒で処理が完了しました。


まぁ、OSとかフレームワークとかで、土俵が違うのも関係しているのかも知れませんが、
携帯端末とPCの処理性能には、まだまだ差がありますね。


私のタブレットPCは5000円の激安品でしたから、普通のタブレットはもっと速いかも…。

tag:

コメント

最近、数学で相対度数をやったのでかなりしっくり来る話題でした。

  • 2013/03/11(月) 22:20:31 |
  • URL |
  • AsaBon #-
  • [ 編集 ]

C#は新しい言語なので、Cよりも良い疑似乱数アルゴリズムを
使っているのかと思ったら同じ線形合同法なんですね。

僕も昔のブログで「モンテカルロ法による円周率の近似」に関するものを
書きましたが(思い返すと論文のタイトルみたいですね)
あれもランダムに打った点が円周上に来る割合として円周率を
求めていたので回数が多ければ多いほど精度をましていきました。

  • 2013/03/12(火) 11:50:18 |
  • URL |
  • div9851 #-
  • [ 編集 ]

Re: AsaBon

それはよかったです。
数学は奥が深いですよね。

Re: div9851

アルゴリズム系の解説には自信がありませんが…。
.NETのRandomクラスは線形合同法ではありません。
「引き算法」というのを使用しているそうです。

乱数を生成する: .NET Tips: C#, VB.NET
http://dobon.net/vb/dotnet/programing/random.html

暗号に使うための複雑な乱数ジェネレータも.NETにはあるみたいですね。


モンテカルロ法で円周率がとれるのは、
この記事で書いてあるように乱数の出現確率が均等になるからです。
回数が多いほど精度が増すのも、出現確率が均等になってゆくためです。

モンテカルロ法もこの記事で書いてある現象を利用しているんですね。

おお、どうやらそうらしいですね。
やはり、ネットの情報は1箇所だけを信用したらダメだなー。

  • 2013/03/12(火) 19:13:20 |
  • URL |
  • div9851 #-
  • [ 編集 ]

コメントの投稿

トラックバック

トラックバック URL
http://cyberboy6.blog.fc2.com/tb.php/251-ab9d12f2
この記事にトラックバックする(FC2ブログユーザー)

当ブログをご利用(閲覧等)になる場合は必ず「当ブログの利用規定」をお守りください。