LoginSignup
0
1

More than 3 years have passed since last update.

宝くじは儲かるのか?~LOTO7と大数の法則~

Posted at

はじめに

「宝くじは儲かるのか?」という問いですが、結論から言います。

儲かりません。

宝くじは、主催者側の利益が極めて大きい事業です。当選金額の還元率は50%を下回ります1。これは競馬、競輪、競艇、オートレースの75%前後と比べて圧倒的に低い値です。しかも、当選はランダムに決まる為、競馬の様な予想も不可能です。作家の橘玲氏はこれを「愚か者に課せられた税金」と表現しています。

しかしながら、勝算があるとすれば、当選金額のランダムな揺らぎが大きい小口で買う場合でしょう。確率論に「大数の法則」というものがあります。ある確率分布から標本を抽出して平均を出す時、その平均は確率分布の真の平均に収束していくという法則です。では、標本数が小さい場合であれば、ランダムな揺らぎにより元が取れる可能性が高まるのではないか?これを確かめてみようと思います。

環境

  • Windows 10
  • Python 3.8.3
  • Jupyterlab Version 2.1.5

実験

宝くじにも色々ありますが、今回はLOTO7を選びました。理由は一等が極めて高額で話題性が高く、いかにも「宝くじらしい」からです。また、一般的な例について検討したかったので、キャリーオーバーは今回は考えませんでした。当選口数による当選金額の変動も考えていません。下に、Loto7の当選金額を計算するクラスを作成しました。

import numpy as np

class Loto7:
    """
    Loto7の当選金額を計算するクラス
    """
    def __init__(self, main_nums, bonus_nums):
        self.main_nums = set(main_nums) # 本数字
        self.bonus_nums = set(bonus_nums) # ボーナス数字

    def prize_amount(self, nums=None):
        nums = self.rand() if nums is None else set(nums)
        diff_main = self.main_nums & nums
        len_main = len(diff_main) # 本数字との一致数
        diff_bonus = self.bonus_nums & nums
        len_bonus = len(diff_bonus) # ボーナス数字との一致数

        if len_main == 7: # 1st prize
            return 600_000_000
        if len_main == 6: # 2nd and 3rd
            return 7_300_000 if len_bonus == 1 else 730_000
        if len_main == 5: # 4th
            return 9_100
        if len_main == 4: # 5th
            return 1_400
        if len_main == 3 and len_bonus > 0: # 6th
            return 1_000
        else:
            return 0

    def rand(self): # ランダムな数字を選択
        r = np.random.choice(np.arange(1,38), 7, replace=False)
        return set(r)

上で定義したクラスを使って、ランダムに数字を選んで当選金額を計算します。計算の仕方は、以下です。

  1. 宝くじをランダムな番号でn本買ったとして、当選金額の合計を出す
  2. それをnで割って一本当たりの金額を出す
  3. 上記を決まった数だけ繰り返して、一本当たりの当選金額の分布を出す
  4. 上記について、nを色々な値で試す

また、当選番号である本数字とボーナス数字は固定にしました。実際の手続きとして、これらの番号はランダムに決まると考えられるので、購入者が決める番号との関係で考えれば、固定でも差し支えないと考えました。

lt7 = Loto7([1,2,3,4,5,6,7], [8,9]) # 当選番号である本数字とボーナス数字は固定
n_lots = list(range(1,10)) + list(range(10,30,2)) + [30, 100, 300, 1000] # 買う宝くじの本数
reps = 1000 # 購入の繰り返しの回数
prize_amounts = [sum([lt7.prize_amount() for i in range(n)]) / n for n in n_lots for r in range(reps)]
prize_amounts = np.array(prize_amounts).reshape(len(n_lots), reps)

これで計算が済みました。では、LOTO7の一枚の購入価格300円以上の当選金額があるケースはどのくらいあるのでしょうか?以下に、購入枚数と「元が取れた割合」の関係を示したグラフを描きます。

recovery_rate = np.apply_along_axis(lambda x: (x >= 300).sum() / len(x), 1, prize_amounts)

plt.plot(n_lots, recovery_rate);
plt.xscale('log')
plt.xlabel('number of LOTO7 tickets')
plt.ylabel('recovery rate')
plt.show()

loto7graph.png

print(n_lots)
print(recovery_rate)

# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 100, 300, 1000]
# [0.042 0.083 0.104 0.062 0.018 0.024 0.022 0.025 0.019 0.014 0.018 0.017
#  0.022 0.012 0.009 0.024 0.024 0.024 0.024 0.028 0.002 0.008 0.011]

これから分かることは、以下の二つです。

  • 最も「元が取れる」購入枚数は3枚
  • その場合、10%程度の確率で元が取れる

結論。

儲かりません。

賢明な人は宝くじは止めましょう!

以上。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1