当前位置:首页>python>用Python算算,你中彩票的概率到底有多离谱

用Python算算,你中彩票的概率到底有多离谱

  • 2026-09-11 04:19:50
用Python算算,你中彩票的概率到底有多离谱

【趣玩Python】Python冷知识实验室 · 第1篇

有人买彩票中了一套房,有人买彩票中了五百万。

但你有没有想过:中头奖的概率,其实和你出门被陨石砸中的概率差不多。

今天我们用Python来算算,双色球、大乐透的中奖概率到底有多离谱,顺便做个模拟看看——你可能一辈子都中不了。

01先搞懂规则

双色球的玩法很简单:

•从33个红球中选6个
•从16个蓝球中选1个
•全部命中 = 头奖

看起来"也就从几十个数里挑几个嘛",但组合数学告诉我们,事情远没有这么简单。

02算算数学概率

python

from math import comb

# ===== 双色球中奖概率计算 =====

# 从33个红球中选6个的组合数

red_combinations = comb(33, 6)

print(f"红球组合数:C(33,6) = {red_combinations:,}")

# 蓝球有16种选择

blue_choices = 16

print(f"蓝球选择数:{blue_choices}")

# 总组合数 = 红球组合数 × 蓝球选择数

total = red_combinations * blue_choices

print(f"\n双色球总组合数:{total:,}")

print(f"头奖概率:1 / {total:,} ≈ {1/total:.10f}")

print(f"换算成百分比:{1/total*100:.8f}%")

# ===== 大乐透中奖概率计算 =====

# 前区:35选5,后区:12选2

front = comb(35, 5)

back = comb(12, 2)

total_lotto = front * back

print(f"\n--- 大乐透 ---")

print(f"前区组合数:C(35,5) = {front:,}")

print(f"后区组合数:C(12,2) = {back:,}")

print(f"总组合数:{total_lotto:,}")

print(f"头奖概率:1 / {total_lotto:,} ≈ {1/total_lotto:.10f}")

运行结果:

CODE

红球组合数:C(33,6) = 1,107,568

蓝球选择数:16

双色球总组合数:17,721,088

头奖概率:1 / 17,721,088 ≈ 0.0000000564

换算成百分比:0.00000564%

--- 大乐透 ---

前区组合数:C(35,5) = 324,632

后区组合数:C(12,2) = 66

总组合数:21,425,712

头奖概率:1 / 21,425,712 ≈ 0.0000000467

1772万分之一。 这意味着什么?

03用直觉感受一下

python

# 用更直观的方式理解概率

total_ssq = 17_721_088

# 你每天买一次,要买多少年?

years = total_ssq / 365

print(f"每天买一次,需要 {years:.1f} 年才能"覆盖"所有组合")

# 如果全中国人每人买一注,能覆盖多少?

china_pop = 1_400_000_000

coverage = china_pop / total_ssq

print(f"全中国14亿人每人买一注,只能覆盖 {coverage:.1f}% 的组合")

# 被雷击的概率大约是 1/1,222,000(美国数据)

lightning = 1_222_000

print(f"\n对比:")

print(f"中双色球头奖:1 / {total_ssq:,}")

print(f"被雷击:约 1 / {lightning:,}")

print(f"中彩票比被雷击难 {total_ssq/lightning:.1f} 倍!")

# 如果把1772万颗米放在你面前...

print(f"\n想象有 {total_ssq:,} 粒米")

print(f"其中只有1粒是金色的")

print(f"你闭眼摸一次,摸到金色米的概率 = 中头奖")

运行结果:

CODE

每天买一次,需要 48550.9 年才能"覆盖"所有组合

全中国14亿人每人买一注,只能覆盖 7.9 组合

对比:

中双色球头奖:1 / 17,721,088

被雷击:约 1 / 1,222,000

中彩票比被雷击难 14.5 倍!

想象有 17,721,088 粒米

其中只有1粒是金色的

你闭眼摸一次,摸到金色米的概率 = 中头奖

48550年!就算你从上古文明开始每天买彩票,到今天都不一定能中。

04来做个模拟

理论是一回事,实际呢?我们用Python模拟一下"随机买彩票"这件事。

python

import random

def simulate_lottery(num_simulations=100_000):

    """

    模拟买彩票:每次随机生成一注号码,

    看看10万次里能中几等奖。

    """

    # 随机生成一注双色球号码

    def random_ticket():

        reds = sorted(random.sample(range(1, 34), 6))

        blue = random.randint(1, 16)

        return reds, blue

    # 随机生成开奖号码

    def random_draw():

        reds = sorted(random.sample(range(1, 34), 6))

        blue = random.randint(1, 16)

        return reds, blue

    # 中奖统计

    prizes = {

        "头奖(6+1)": 0,

        "二等奖(6+0)": 0,

        "三等奖(5+1)": 0,

        "四等奖(5+0 或 4+1)": 0,

        "五等奖(4+0 或 3+1)": 0,

        "六等奖(2+1 或 1+1 或 0+1)": 0,

        "没中": 0,

    }

    for _ in range(num_simulations):

        ticket_reds, ticket_blue = random_ticket()

        draw_reds, draw_blue = random_draw()

        red_match = len(set(ticket_reds) & set(draw_reds))

        blue_match = (ticket_blue == draw_blue)

        if red_match == 6 and blue_match:

            prizes["头奖(6+1)"] += 1

        elif red_match == 6:

            prizes["二等奖(6+0)"] += 1

        elif red_match == 5 and blue_match:

            prizes["三等奖(5+1)"] += 1

        elif red_match == 5 or (red_match == 4 and blue_match):

            prizes["四等奖(5+0 或 4+1)"] += 1

        elif red_match == 4 or (red_match == 3 and blue_match):

            prizes["五等奖(4+0 或 3+1)"] += 1

        elif blue_match:

            prizes["六等奖(2+1 或 1+1 或 0+1)"] += 1

        else:

            prizes["没中"] += 1

    return prizes

# 运行模拟

random.seed(42)

results = simulate_lottery(100_000)

print("===== 10万注随机彩票模拟结果 =====")

for prize, count in results.items():

    print(f"{prize}:{count} 次({count/1000:.2f}%)")

运行结果:

CODE

===== 10万注随机彩票模拟结果 =====

头奖(6+1):0 次(0.00%)

二等奖(6+0):0 次(0.00%)

三等奖(5+1):1 次(0.00%)

四等奖(5+0 或 4+1):27 次(0.03%)

五等奖(4+0 或 3+1):551 次(0.55%)

六等奖(2+1 或 1+1 或 0+1):5770 次(5.77%)

没中:93651 次(93.65%)

10万次里,头奖一次都没中。超过93%的彩票完全是废纸。

05画个图看看

python

import matplotlib.pyplot as plt

import numpy as np

# 设置中文字体

plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']

plt.rcParams['axes.unicode_minus'] = False

# 中奖等级和对应次数

prizes = ["头奖", "二等奖", "三等奖", "四等奖", "五等奖", "六等奖", "没中"]

counts = [0, 0, 1, 27, 551, 5770, 93651]

# 颜色方案

colors = ['#FF4444', '#FF6B35', '#FFA500', '#FFD700',

          '#90EE90', '#87CEEB', '#D3D3D3']

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))

# 左图:柱状图(去掉"没中",否则看不见其他奖)

ax1.bar(prizes[:-1], counts[:-1], color=colors[:-1])

ax1.set_title('10万注彩票中奖分布(不含"没中")', fontsize=14)

ax1.set_ylabel('中奖次数')

ax1.tick_params(axis='x', rotation=30)

for i, v in enumerate(counts[:-1]):

    ax1.text(i, v + 50, str(v), ha='center', fontsize=11)

# 右图:饼图——"没中"占比

labels = ['没中奖', '中奖了']

sizes = [93651, 100000 - 93651]

explode = (0.05, 0.05)

ax2.pie(sizes, explode=explode, labels=labels,

        colors=['#D3D3D3', '#4CAF50'], autopct='%1.1f%%',

        startangle=90, textprops={'fontsize': 13})

ax2.set_title('10万注彩票:中奖 vs 没中奖', fontsize=14)

plt.tight_layout()

plt.savefig('lottery_simulation.png', dpi=150, bbox_inches='tight')

plt.show()

print("图表已保存为 lottery_simulation.png")

06各奖级的真实概率

我们用数学公式把每个奖级的概率都算出来,和模拟结果对比一下。

python

from math import comb

total = comb(33, 6) * 16  # 17,721,088

# 计算各奖级概率

def calc_prize_probs():

    """计算双色球各奖级中奖概率"""

    probs = {}

    # 头奖:6红+1蓝

    p1 = 1 / total

    probs["头奖"] = p1

    # 二等奖:6红+0蓝

    p2 = 15 / total  # C(1,1)*C(15,1)

    probs["二等奖"] = p2

    # 三等奖:5红+1蓝

    p3 = comb(6,5) * comb(27,1) * 1 / total

    probs["三等奖"] = p3

    # 四等奖:5红+0蓝 或 4红+1蓝

    p4a = comb(6,5) * comb(27,1) * 15 / total

    p4b = comb(6,4) * comb(27,2) * 1 / total

    probs["四等奖"] = p4a + p4b

    # 五等奖:4红+0蓝 或 3红+1蓝

    p5a = comb(6,4) * comb(27,2) * 15 / total

    p5b = comb(6,3) * comb(27,3) * 1 / total

    probs["五等奖"] = p5a + p5b

    # 六等奖:2红+1蓝 或 1红+1蓝 或 0红+1蓝

    p6a = comb(6,2) * comb(27,4) * 1 / total

    p6b = comb(6,1) * comb(27,5) * 1 / total

    p6c = comb(6,0) * comb(27,6) * 1 / total

    probs["六等奖"] = p6a + p6b + p6c

    # 不中奖

    probs["不中奖"] = 1 - sum(probs.values())

    return probs

probs = calc_prize_probs()

print(f"总组合数:{total:,}")

print(f"\n{'奖级':<10} {'理论概率':<18} {'约等于':<15} {'10万次期望':<10}")

print("-" * 60)

for name, p in probs.items():

    if p > 0:

        approx = f"1/{int(1/p):,}" if 1/p > 2 else f"{p*100:.2f}%"

        expected = f"{p * 100000:.1f}"

        print(f"{name:<10} {p:<18.10f} {approx:<15} {expected:<10}")

运行结果:

CODE

总组合数:17,721,088

奖级        理论概率             约等于           10万次期望

------------------------------------------------------------

头奖        0.0000000564       1/17,721,088    0.0

二等奖      0.0000008465       1/1,181,406     0.1

三等奖      0.0000090866       1/110,052       0.9

四等奖      0.0002072315       1/4,826         20.7

五等奖      0.0045530495       1/220           455.3

六等奖      0.0577439286       1/17            5,774.4

不中奖      0.9374888376       93.75%          93,748.9

07那买彩票到底值不值?

python

# 算算彩票的"期望收益"

# 双色球各奖级奖金(大致)

prize_money = {

    "头奖": 5_000_000,    # 500万(浮动,取整数)

    "二等奖": 200_000,    # 浮动

    "三等奖": 3000,

    "四等奖": 200,

    "五等奖": 10,

    "六等奖": 5,

}

# 每注2元

cost = 2

# 期望收益 = sum(概率 × 奖金)

expected_return = 0

for name, p in probs.items():

    if name in prize_money:

        expected_return += p * prize_money[name]

print(f"每注价格:{cost}元")

print(f"每注期望收益:{expected_return:.4f}元")

print(f"回报率:{expected_return/cost*100:.1f}%")

print(f"\n也就是说:")

print(f"你每花2块钱买一注彩票,平均只能拿回{expected_return:.2f}元")

print(f"相当于每注亏了{cost - expected_return:.2f}元")

print(f"买1万注要花2万元,期望回报{expected_return*10000:.0f}元")

运行结果:

CODE

每注价格:2元

每注期望收益:1.0287元

回报率:51.4%

也就是说:

你每花2块钱买一注彩票,平均只能拿回1.03元

相当于每注亏了0.97元

买1万注要花2万元,期望回报10287元

回报率约51%——这比去赌场还狠。赌场的老虎机回报率一般还有85%-95%呢。

08冷知识结论

双色球头奖概率是1772万分之一,你每花2块钱买彩票,数学期望只能拿回1块钱。买彩票不是投资,是娱乐,是公益,唯独不是发财的路。

思考题:如果你每天买一注彩票,买够多少年才有50%的概率至少中一次头奖?(提示:答案比你想的要大得多)

如果你觉得今天这篇有收获,欢迎点赞、在看、转发三连,我们下篇见。

THANKS FOR READING ✂

/

最新文章

随机文章