Python

ガチャの確率をpythonを使用して計算するプログラムを組む

2020/09/05

今回はガチャの確率をpyhonを使用して簡単に導き出せないかと考えて、簡単なプログラムを組むことにしてみました。

ガチャの確率プログラム

今回は一覧で確認できるようにしたものです。
もう少し作りこんでいけば対話型のプログラム作成できそうですが、めんどいので途中までの計算のみで終わりました。

とりあえず、面倒な計算とかは置いておきプログラムの紹介。

# -*- coding: utf-8 -*-

import math

a = 0.05 #当たる確率
not_a = 1 - a #外れる確率
n = 50 #試行回数
hit = 5 #当たる回数

#一回も当たらない確率
no_hit_perfomance = not_a ** n


#組み合わせの総数と確率の計算
def performance_function(hit_count):
    
    #組み合わせの総数
    c = math.factorial(n) // (math.factorial(n - hit_count) * math.factorial(hit_count))
    #確率の計算
    p = c * a ** hit_count
    performance = p * not_a **(n - hit_count)
    
    return performance

for hit_count in range(hit + 1):
    
    if hit_count == 0:
        print("当選回数{}回\t確率:{}".format(hit_count,no_hit_perfomance))
    else:
        #hit回数当たる確率
        print("当選回数{}回\t確率:{}".format(hit_count,performance_function(hit_count)))

failure_perfomance = 0
for hit_count in range(hit):
    
    if hit_count == 0:
        #一回以上当たる確率
        total_performance = 1 - no_hit_perfomance
        print("当選回数{}回以上\t確率:{}".format(hit_count + 1,total_performance))
    else:
        #hit回数以上当たる確率
        failure_perfomance += performance_function(hit_count)
        total_performance = 1 - no_hit_perfomance - failure_perfomance
        print("当選回数{}回以上\t確率:{}".format(hit_count + 1,total_performance))

これで上手く動けば、こんな感じで表示がされる。

当選回数0回 確率:0.07694497527671315
当選回数1回 確率:0.20248677704398216
当選回数2回 確率:0.2611013703988193
当選回数3回 確率:0.21987483823058493
当選回数4回 確率:0.13597522890575658
当選回数5回 確率:0.06584063715436642
当選回数1回以上 確率:0.9230550247232868
当選回数2回以上 確率:0.7205682476793047
当選回数3回以上 確率:0.45946687728048535
当選回数4回以上 確率:0.23959203904990045
当選回数5回以上 確率:0.10361681014414381

計算の方法さえわかってしまえば割と簡単に作成できました。
ここからは計算も含めてどのようにプログラムに落とし込んでいったかを説明していきます。

当選回数0回の確率

計算の方法が不明だったため、ガチャの確率計算を参考にして作成いたしました。

当選回数が0回のときから先に説明していきます。

試行回数n回のときに当選回数が0回の場合(当たる確率:a,外れる確率:not_a = 1 - a)

not_an

今回の場合は試行回数が50回で外れる確率は0.95となっています。(当たる確率:0.05,外れる確率:0.95 = 1 - 0.05)

0.9550

計算すると0.07694497527671315のため約8%になります。
これを計算しているプログラムが下記です。

# -*- coding: utf-8 -*-

import math

a = 0.05 #当たる確率
not_a = 1 - a #外れる確率
n = 50 #試行回数
hit = 5 #当たる回数

#一回も当たらない確率
no_hit_perfomance = not_a ** n

当選回数1回の確率

当選回数が1・2回などの場合の計算方法は0回のときと異なるためご説明していきます。

試行回数n回で当選回数が1回の場合

まず組み合わせの総数を求めます。数式で表すと

nC1

今回の場合は試行回数50回で当選回数1回なので

50C1 = 50通り

例えば試行回数50回で当選回数2回の場合

50C2 = 1225通り

これの計算をdefでperformance_functionとして関数として定義しています。

組み合わせの総数がわかったら今度は確率の計算をしていきます。

試行回数n回で当選回数1回の場合(当たる確率:a,外れる確率:not_a = 1 - a)

nC1a1not_an-1

この辺からめんどくさい数式で表されてきていますが、数字をいれてみると意外とわかりやすかったりします。

今回の場合は試行回数50回で当選回数1回(当たる確率:0.05,外れる確率:0.95 = 1 - 0.05)

50C10.0510.9549 = 50*0.05*0.9549

計算すると確率:0.202486777043982とでますので、20%ぐらいになりますね。

プログラムに起こすと下記の表現にしています。

# -*- coding: utf-8 -*-

import math

a = 0.05 #当たる確率
not_a = 1 - a #外れる確率
n = 50 #試行回数
hit = 5 #当たる回数

#一回も当たらない確率
no_hit_perfomance = not_a ** n


#組み合わせの総数と確率の計算
def performance_function(hit_count):
    
    #組み合わせの総数
    c = math.factorial(n) // (math.factorial(n - hit_count) * math.factorial(hit_count))
    #確率の計算
    p = c * a ** hit_count
    performance = p * not_a **(n - hit_count)
    
    return performance

for hit_count in range(hit + 1):
    
    if hit_count == 0:
        print("当選回数{}回\t確率:{}".format(hit_count,no_hit_perfomance))
    else:
        #hit回数当たる確率
        print("当選回数{}回\t確率:{}".format(hit_count,performance_function(hit_count)))


組み合わせの総数の計算方法は下記サイトを参考にしました。
Pythonで階乗、順列・組み合わせを計算、生成

当選回数1回以上の確率

各個別の当選確率を知りたいわけではなくて、1回以上や2回以上などの当選確率を知りたい場合もあると思います。
ガチャでとりあえず1体以上は欲しいのだけど、それって何%なん?みたいな。

その場合の確率の求め方も計算していきます。
基本の求め方

1 - 失敗の確率

試行回数n回のときに当選回数が1回以上の場合(当たる確率:a,外れる確率:not_a = 1 - a)

1 - not_an

当選回数0回の確率を1から引けば1回以上の確率を求めることができます。

今回の場合は試行回数50回で当選回数1回以上なので

1 - 0.9550

計算すると0.9550は約8%なので、1回以上当たる確率は92%になります。

プログラムにするとこんな感じ。no_hit_perfomanceが失敗の確率

# -*- coding: utf-8 -*-
import math

a = 0.05 #当たる確率
not_a = 1 - a #外れる確率
n = 50 #試行回数
hit = 5 #当たる回数

#一回も当たらない確率
no_hit_perfomance = not_a ** n

failure_perfomance = 0
for hit_count in range(hit):
    
    if hit_count == 0:
        #一回以上当たる確率
        total_performance = 1 - no_hit_perfomance
        print("当選回数{}回以上\t確率:{}".format(hit_count + 1,total_performance))

当選回数2回以上の確率

当選回数2回以上の場合の確率は計算方法が異なります。

2回以上の場合の計算方法は

1 - 失敗の確率(0回の当選確率) - 失敗の確率(1回の当選確率)

計算式にすると試行回数n回で当選回数2回以上の場合(当たる確率:a,外れる確率:not_a = 1 - a)

1 - not_an - nC1a1not_an-1

計算式にするとわかりずらいので計算していきます。

1 - 0.9550 - 50*0.05*0.9549

計算すると1から28%引くことになりますので、72%が2回以上当選する確率になります。

それをプログラムに起こしていきます。

# -*- coding: utf-8 -*-

import math

a = 0.05 #当たる確率
not_a = 1 - a #外れる確率
n = 50 #試行回数
hit = 5 #当たる回数

#一回も当たらない確率
no_hit_perfomance = not_a ** n


#組み合わせの総数と確率の計算
def performance_function(hit_count):
    
    #組み合わせの総数
    c = math.factorial(n) // (math.factorial(n - hit_count) * math.factorial(hit_count))
    #確率の計算
    p = c * a ** hit_count
    performance = p * not_a **(n - hit_count)
    
    return performance

failure_perfomance = 0
for hit_count in range(hit):
    
    if hit_count == 0:
        #一回以上当たる確率
        total_performance = 1 - no_hit_perfomance
        print("当選回数{}回以上\t確率:{}".format(hit_count + 1,total_performance))
    else:
        #hit回数以上当たる確率
        failure_perfomance += performance_function(hit_count)
        total_performance = 1 - no_hit_perfomance - failure_perfomance
        print("当選回数{}回以上\t確率:{}".format(hit_count + 1,total_performance))

failure_perfomanceにhit_countの回数分の失敗の確率を足していくことでトータルの失敗の確率を求めます。
そして、total_performanceの計算は以下になります。

total_performance = 1 - no_hit_perfomance - failure_perfomance

0回の失敗の確率とhit_countの回数分の失敗の確率の総数を1から引くことで当選の確率を求めることができます。

まとめ

今回は計算式をプログラムに落とす手順を簡単にまとめてみました。
割と計算式を理解するのに時間がかかり、プログラムに落とし込むのはそこまでかからなかったりします。

それよりも、この文章を書いている時間のほうがプログラム作成よりも時間がかかったりします。笑
今回はガチャの確率をプログラムで作成したので、自身が回すガチャで試行回数が100回のときに何%ぐらいの確率があるのか計算してみるのもいいかもしれませんね。

-Python