Pythonで当選率10%のくじを10回引く(完成編)~確率の悪魔 vs Python ep 2~

python
python

episode 1で、くじ引き10回プログラムができた。
次は、さらにその確率を求めよう。

前回記事:Pythonで当選率10%のくじを10回引く ~確率の悪魔 vs Python ep1 ~

前回の振り返りです。
今回の目標は、「10%の確率で当たるくじを、10回引いた時にあたる確率は計算上では、65.13%であるが、本当にそうなるかを検証する」ということでした。
episode 1では、「10%の確率で当たるくじを、10回引いた時にあたったかどうか判定する」というプログラム」を作るところまでできました。

では、今回は、このプログラム=「10回判定プログラム」を繰り返して、確率計算を行っていきたいと思います。(2021年2月28日:学習開始9日目、PyQさんで学習中!

オンラインPython学習サービス「PyQ™(パイキュー)」


今回は、この曲とともにお届けします。
映画「007 カジノ・ロワイヤル」の主題歌!
クリス・コーネルさんのYou Know My Name (From “Casino Royale” Soundtrack)
(曲名からYouTube公式動画に飛びます。鬼歌ウマです。)


(出来上がったコードをすべてコピペする事で、各自のPCで遊べます。やり方は「10分でプログラマーになろう ~100000000人をごぼう抜き~」参考にしてください)

1.作戦会議

作戦を立てましょう!

「10回判定プログラム」を何回も繰り返して確率を出します。いったん、10回繰り返して判定してみましょう。
前回同様、フローチャートを書いてみましょう

こんな感じで書いてみました。
書いてみて分かりましたが、大きな構造は、episode 1で書いたものと似ているように思います。
ということは、同じ構造の入れ子みたいになるのではないでしょうか?

ではコードを書いていきましょう。

2.コードを書いていこう①

初めに前回のコードを振り返ります。

import random
#引いた回数
hiku_num = 0
#あたり回数
atari_count = 0
#くじをつくる
kuji = ['〇', '×1', '×2','×3','×4','×5','×6','×7','×8','×9',]
while True:
    if hiku_num == 10:
        break
    else:
        #くじをひく your_kujiが引いたくじ
        your_kuji = random.choice(kuji)
        #〇ならあたり、×ならはずれ
        #print(your_kuji)
        hiku_num += 1
        if your_kuji == '〇':
           #print('あたり')
            atari_count += 1
        else:
            #print('はずれ')
            pass
if atari_count == 0:
    print('全滅!')
else:
    print('あたりあった!')

まずは、「10回判定プログラムの試行回数」と「10回判定プログラムであたりが出た回数」を定義しましょう。

#10回判定プログラム試行数
prog_num = 0
#10回判定プログラムあたり回数
prog_atari_num = 0

つぎは、「10回判定プログラムであたれば、10回判定プログラムであたりが出た回数を増やす」「あたりが出なければスルー」を書きましょう。
10回判定プログラム中に入れたらいいのではないでしょうか?

        else:
            print('あたりあった!')
            prog_atari_num += 1

こんな感じです。あたりがない場合は、今までと同じなので変更いらないですね。

では、次は、「10回判定プログラムが1周すれば、プログラム試行数を1増やす」ですね。

while True:
    if hiku_num == 10:
        prog_num += 1
        break

ここまでで、「10回判定プログラム」の修正ができました。一旦区切りましょう。

3.コードを書いていこう①

続いて、修正した「10回判定プログラム」が10回試行されるまで繰り返しましょう。
今までのものをwhileで繰り返しましょう。

while True:
    #10回判定プログラム試行数が10回になるまで繰り返す。
    if prog_num == 10:
        break
    else:
        while True:
            #~~~略~~

どうでしょうか?一度動かしてみましょう
一番下にprintで試行回数とあたり回数を出力できるようにしました。
(後で分かりますが、下記プログラムは誤りがあります。どこでしょうか?)

import random
#10回判定プログラム試行数
prog_num = 0
#10回判定プログラムあたり回数
prog_atari_num = 0
#引いた回数
hiku_num = 0
#あたり回数
atari_count = 0
#くじをつくる
kuji = ['〇', '×1', '×2','×3','×4','×5','×6','×7','×8','×9',]
while True:
    #10回判定プログラム試行数が10回になるまで繰り返す。
    if prog_num == 10:
        break
    else:
        while True:
            if hiku_num == 10:
                prog_num += 1
                break
            else:
                #くじをひく your_kujiが引いたくじ
                your_kuji = random.choice(kuji)
                #〇ならあたり、×ならはずれ
                #print(your_kuji)
                hiku_num += 1
                if your_kuji == '〇':
                #print('あたり')
                    atari_count += 1
                else:
                    #print('はずれ')
                    pass
        if atari_count == 0:
            print('全滅!')
        else:
            print('あたりあった!')
            prog_atari_num += 1
print('試行回数',prog_num)
print('あたりが出た回数',prog_atari_num)

では動かした結果です。

あたりあった!
あたりあった!
あたりあった!
あたりあった!
あたりあった!
あたりあった!
あたりあった!
あたりあった!
あたりあった!
あたりあった!
試行回数 10
あたりが出た回数 10

10回繰り返せていますが、何かおかしいですね・・・どこかで間違ったようです
(この間いろいろとコードを見直すこと10分)

どうやら、1回目の結果をそのまま出力してるっぽいです。
「引いた回数」と「あたりの回数」が上の方で定義されていて、1週目で引いた回数=10になってしまったら、それが引き継がれて2週目以降は引かずに1週目の結果でスルーしているという事の良いです。

という事は、1週回すごとに「引いた回数」と「あたりの回数」がリセットされれば良いのではないでしょうか?
どこで、リセットするか?1回あたりの判定が出た直後でいいのではないでしょうか?修正箇所だけ抜粋します。

        if atari_count == 0:
            print('全滅!')
        else:
            print('あたりあった!')
            prog_atari_num += 1
        hiku_num = 0
        atari_count = 0

動かしてみましょう

あたりあった!
あたりあった!
あたりあった!
あたりあった!
あたりあった!
全滅!
あたりあった!
あたりあった!
あたりあった!
あたりあった!
試行回数 10
あたりが出た回数 9

できたっぽいです。今回は10回試行中9回あたりなので、90%です。
計算と大きく異なりますね。おそらく試行回数が足りていないと思います。
その前に確率を算出するプログラムを書きましょう。

#確率計算
prob = 100*(prog_atari_num/prog_num)
print('確率は', prob, '%')

試行回数を100回にしてみましょう。あと、毎回「あたり」「全滅」が出るのが面倒なので、printを消しましょう。
修正しているのは、
・14行目:if prog_num == 100: (数字変更)
・34行目:#print(‘全滅!’)
・35行目:pass (34行目を消したため、エラーがでました。)
・37行目:#print(‘あたりあった!’)

import random
#10回判定プログラム試行数
prog_num = 0
#10回判定プログラムあたり回数
prog_atari_num = 0
#引いた回数
hiku_num = 0
#あたり回数
atari_count = 0
#くじをつくる
kuji = ['〇', '×1', '×2','×3','×4','×5','×6','×7','×8','×9',]
while True:
    #10回判定プログラム試行数が10回になるまで繰り返す。
    if prog_num == 100:
        break
    else:
        while True:
            if hiku_num == 10:
                prog_num += 1
                break
            else:
                #くじをひく your_kujiが引いたくじ
                your_kuji = random.choice(kuji)
                #〇ならあたり、×ならはずれ
                #print(your_kuji)
                hiku_num += 1
                if your_kuji == '〇':
                #print('あたり')
                    atari_count += 1
                else:
                    #print('はずれ')
                    pass
        if atari_count == 0:
            #print('全滅!')
            pass
        else:
            #print('あたりあった!')
            prog_atari_num += 1
        hiku_num = 0
        atari_count = 0
print('試行回数',prog_num)
print('あたりが出た回数',prog_atari_num)
#確率計算
prob = 100*(prog_atari_num/prog_num)
print('確率は', prob, '%')

ではその結果です。

試行回数 100
あたりが出た回数 74
確率は 74.0 %

計算上の確率に近づいてきました。
もっと試行回数を増やしてみましょう。if prog_num == の数字を変えて試してみました。

試行回数 1000
あたりが出た回数 650
確率は 65.0 %
試行回数 10000
あたりが出た回数 6437
確率は 64.37 %
試行回数 1000
あたりが出た回数 650
確率は 65.0 %
試行回数 10000
あたりが出た回数 6437
確率は 64.37 %
試行回数 100000
あたりが出た回数 65315
確率は 65.315 %

おお!計算上の確率65.13%に近づいてきました。

これにて、検証終了です。・・・がまだ終わりません。
せっかく作ったので、次回、もうちょっと遊んでみようと思います。

To Be Continued : 確率の悪魔 vs Python episode 3

PyQさんで勉強中!

コメント

タイトルとURLをコピーしました