課題
コイン投げのシミュレーションは次の要領で行うことにします.
- 整数mを(実行時に)指定する(ただし0 < m <100).
- コインを投げる回数nを(実行時に)指定する(ただし n > 0).
- 確率m/100(つまりm%)で表が出るコインをn回投げる(仮想的な)試行を行う. 試行の結果は適宜画面に表示する.
- 試行中に表が出た回数(count)を数えておいて,試行終了後に表が出た割合(rate)を画面に示す.またその値を期待値(m/100)と比較する.
m,nは条件を満たすように適切に指定されると仮定して構いません. 想定外の値が指定された場合の処理(例外処理)は考えなくても構いません.
想定する実行例
プログラムのファイル名が仮に「coin_toss.rb」であったとして, 想定される実行例を示します.
$ ruby coin_toss.rb 75 20
O@@@O@@O@@@O@OO@O@@@
RESULT: 0.650(13/20)
EXPECTED: 0.750
プログラムの処理の概要を示します.
- 実行の際,プログラムファイル名(coin_toss.rb)に加えて,表が出る確率(m[%])とコインを投げる回数(n)をこの順で指定します. 上の例では表が出る確率を75%,投げる回数を20回と指定しています. プログラムにおいて,これらの数を読み取って変数に格納する方法については,以下で説明します.
- プログラムが実行されたら,まずn回のコイン投げの結果を一列に並べて表示します. コインを投げたときに出た面が「表」であるか「裏」であるかは,それぞれ適当な記号で表すことにします. 上の例では,表を「@」,裏を「O」で表しています.
- n回のコイン投げが終わったら,最後にシミュレーション全体の結果を表示します.上の例では,試行の結果は表が13回で,表が出た割合(RESULT)が13/20=65%,一方で期待値(EXPECTED)は75%であることを示しています.
[参考] シミュレーションの結果の解析
プログラムが完成したら,コインを投げる回数nによって,シミュレーションの結果がどのように変わるのかについて調べてみてください.
プログラムは確率的な挙動を示すため, 表が出る確率(m/100)とコインを投げる回数(n)が同じであっても,結果が同じになるとは限りません. 指定する値(m,n)を変えないでプログラムを何回か実行してみてください. またコインを投げる回数(n)を大きくしていってみてください. どのような傾向が見られるでしょうか.
プログラムヘッダ
次に示すコードをプログラムの先頭にコピーして入れておくようにしてください(必要事項は記入してください).
=begin
所属:
氏名:
学生番号:
難易度(5段階評価):
感想など(任意)
=end
技術要素
プログラム作成に用いるであろう技術要素を示します.
- コマンドラインで指定される引数の読み込み
このプログラムは上でも示したように試行の設定(m,n)を指定して実行します.$ ruby coin_toss.rb 75 20
プログラムではこのように指定したデータを次のように取得できます.# 1,2番目の引数をそれぞれ整数に変換してM,Nとする # (注: 大文字から始まる名前はRubyでは定数) M = ARGV.shift.to_i # 表が出る確率=M/100 N = ARGV.shift.to_i # 試行回数N # [テスト] 読み込んだ値の確認(課題のプログラムに入れる必要はない) puts "表が出る確率=#{M}%, 試行回数=#{N}"
- ランダムに整数を発生させる(rand)
kが正の整数であるとき,rand(k)は,0,1,2,...,k-1をランダムに返す.# x = 0,1,2,...,99のいずれか(実行するたびに変わりうる) x = rand(100) 10.times do y = rand(100) print "#{y} " end puts '' # ==> 17 61 62 22 88 9 65 9 3 70 # これは飽くまで一例(結果は毎回変わりうる)
今回はrand(k)は0,1,2,...,k-1をそれぞれ等確率(=1/k)で発生させるものとして扱うことにします. - 文字データ
プログラムで引用符で囲った部分('...')は文字データとして扱われます.HEAD = '@' # 表を表す記号(→定数HEADとして定義) TAIL = 'O' # 裏を表す記号(定数TAILとして定義) print HEAD # 「@」を表示(改行なし) print TAIL # 「O」を表示(改行なし)
- 条件演算子と条件式
条件が成り立つかどうかによって,二つの値のどちらかをとる演算子が利用できます.# [条件演算子] (条件) ? (条件が成立するときの値) : (条件が成立しないときの値) # y = xの絶対値(xが正ならxそのもの,そうでないなら-x) y = (x > 0) ? x : -x # scoreが1と等しいなら,result='Win!',そうでなければresult='Lose' result = (score == 1) ? 'Win!' : 'Lose' puts " You, #{result}"
これらの例では,xやscoreは定義していません. テストしてみる場合には先に適当な値を定義してください. テストにはirbを使うとよいでしょう.上の例に示した通り,不等号(<, >)や等号(==)を使って条件を記述できます. なお等号は「==」です.「=」は代入であることに注意してください. 「=」は(文脈に関係なく)常に代入です.上の例で「score = 1」と書くとおかしなことになります.
ちなみに比較演算子としては次のようなものが使えます.
x > y xはyより大きい x >= y xはy以上 x == y xはyと等しい x <= y xはy以下 x < y xはy未満 x != y xはyと等しくない(x ≠ y) - フォーマットを指定した数値の表示
数値データを画面に表示するときに,表示の書式(フォーマット)を指定できます. フォーマットは「%」を使って指示します.次に例を示します.# %d: 整数(桁数は指定しない) # %3d: 整数(右詰め3桁) # %04d: 整数(右詰め4桁,3桁以下なら上位に0を付加する) # %f: 小数点以下も表示(桁数は指定しない) # %.2f: 小数点以下2桁まで表示
これらを使うと,次のようにフォーマット指示子の入ったメッセージに データを当てはめて表示することができます.# rate=0.65,count=13,N=20のとき # 「RESULT: 0.650(13/20)」と表示される(最後に改行される) puts "RESULT: %.3f(%d/%d)" % [rate,count,N]
この例の場合,フォーマット指示子が3つ入っていて, メッセージの後に「%」と組み合せて指定している[rate,count,N]によって, 3つのフォーマット指示子に当てはめるデータを順に定めています. - [参考] sleep
sleep(t)によって,プログラム実行中にt秒間実行を止めておくことができます.sleep(0.1) # 0.1秒停止試行のたびに少しsleepすれば,結果を「ゆっくり」と表示させてホンモノのコイン投げらしく(??)見せかけることができます(試行回数が多い場合は実行時間が長くなって邪魔になるだけでしょう...;-P).
サンプルプログラム
次にサンプルプログラムを示します. 課題のプログラム作成に役立ててください.
これらをブラウザの画面で開いたときに文字化けしてしまう場合には, ダウンロードしてEmacs等で開いてみてください.
[参考] 大数の法則
この課題で示したコイン投げでは「同一回数の試行」を何セットも行ったときに, 1セットでの試行回数(n)を増やすほど, 表が出る割合が期待値に近くなることが多くなることが見て取れるでしょう(セットごとの「表が出る割合」の散らばり具合は小さくなる).
さらに試行回数を増やしていった極限を考えたときに, 表が出る割合は期待値に「収束」することが数学的に知られていて,そのような振る舞いは一般に「大数の法則」と呼ばれています.
日置尋久(HIOKI Hirohisa)
Last modified: Sun Nov 02 15:45:50 JST 2025