Python Code for Computing Generalized Birthday Problem

专业相关2026年3月20日发布 芮和
16.5K 1080
1,619字
7–10 分钟

Problem Description

Generalized Birthday Problem: Consider nn people in a room. Assume each person’s birthday is equally likely to be any of the 365 days of the year (ignoring February 29), and all birthdays are independent. When nn and rr satisfy certain conditions, the probability that at least two people have birthdays within rr days of each other is:

P=1(3651nr)!365n1(365(r+1)n)!P=1-\frac{(365-1-n r)!}{365^{n-1}(365-(r+1) n)!}

Implementation

This is a simple code using Log-Probability Computation to calculate PP. The logarithmic transformation helps prevent numerical overflow and reduces computation errors when dealing with large factorials.

import math

ln = math.log


def calculateP(n, r):
    up = 0
    dl = (n - 1) * ln(365)
    dr = 0

    for i in range(1, 365 - n * r):
        up += ln(i)

    for j in range(1, 365 + 1 - r * n - n):
        dr += ln(j)

    right = math.exp(up - dl - dr)

    return 1 - right


print(calculateP(10, 0))
print(calculateP(20, 0))
print(calculateP(23, 0))
print(calculateP(30, 0))
print(calculateP(40, 0))
print(calculateP(50, 0))

print()

print(calculateP(10, 1))
print(calculateP(20, 1))
print(calculateP(23, 1))
print(calculateP(30, 1))
print(calculateP(40, 1))
print(calculateP(50, 1))

print()

print(calculateP(10, 2))
print(calculateP(20, 2))
print(calculateP(23, 2))
print(calculateP(30, 2))
print(calculateP(40, 2))
print(calculateP(50, 2))
Code language: Python (python)

Results

nr=0r=1r=2
100.11694817770.31471653010.4720877238
200.41143838360.80448335520.9393140224
230.50729723430.88790964370.9770852403
300.70631624270.97819536200.9987474258
400.89123180980.99911544170.9999963536
500.97037357960.99998798310.9999999989

Source

This code is used to solve a problem in the homework of Probability and Statistics for Information Science course. You can find the complete assignment in my GitHub repository (The visibility will be changed to public after the course ends).

© 版权声明

相关文章

108 条评论

  • 船老大
    船老大 游客

    那个 range 边界确定没写错?少加个 1 就废了。

    韩国
    回复
    • 熊本熊
      熊本熊 游客

      边界少1就全错,建议加个注释说明推导过程。

      中国山东@ 船老大
      回复
  • 墨韵居
    墨韵居 游客

    作业题吧?看着像信科专业的硬核内容。

    中国北京
    回复
  • 梦回东京
    梦回东京 游客

    概率飙升得太快,直觉完全跟不上数学。

    中国广东
    回复
  • 旧梦重游
    旧梦重游 游客

    要是人数超过 365 咋办,公式还成立不?

    韩国
    回复
  • 妃色迷离
    妃色迷离 游客

    365 天忽略闰年,这假设在实际里准吗?🤔

    中国河北
    回复
  • 泡泡小精灵
    泡泡小精灵 游客

    之前算阶乘直接爆内存,加个 log 确实稳。

    中国天津
    回复
    • 自由脚印
      自由脚印 游客

      log真是救命稻草,我上次算到100!直接崩了。

      中国@ 泡泡小精灵
      回复
  • 夏夜微风
    夏夜微风 读者

    变量名起得太随意了,up 和 dr 啥意思啊?

    韩国
    回复
    • 琼英
      琼英 游客

      up是累加分子的对数和吧,dr应该是分母?

      中国重庆@ 夏夜微风
      回复
  • 爱吃辣的企鹅
    爱吃辣的企鹅 游客

    r=0 不就是经典生日悖论吗,23 人确实过半。

    日本
    回复
  • 壶中天地
    壶中天地 读者

    这公式看着头大,代码倒是能跑通。

    印度
    回复
  • 铜铃巷
    铜铃巷 游客

    up和dr变量名也太抽象了,读着费劲

    马来西亚
    回复
  • 重明光
    重明光 游客

    直接算阶乘肯定溢出啊,我之前试过😂

    中国北京
    回复
  • 夜啼者
    夜啼者 读者

    这种计算用Stirling近似会不会更快点?

    中国湖北
    回复
  • 星空绘
    星空绘 游客

    r=2的时候概率这么高?感觉有点反直觉。

    韩国
    回复
  • 烈焰Fire
    烈焰Fire 游客

    老哥这代码写得够简洁,变量名省事。

    澳大利亚
    回复
  • 墨枭
    墨枭 读者

    看到那个88%的概率,突然觉得巧合也没那么巧了。

    中国广东
    回复
  • 网络行者
    网络行者 游客

    GitHub链接能贴一下不?想跑跑看结果。

    中国吉林
    回复
  • 小资生活
    小资生活 读者

    这作业看着有点硬核啊,概率论早还给老师了。

    中国广东
    回复
  • 吃货联盟
    吃货联盟 读者

    原来是用log避免溢出,我说怎么直接算阶乘老是报错。

    中国陕西
    回复
  • 炼狱之怒
    炼狱之怒 游客

    那个range的边界看得我有点迷糊,365-n*r确定不用+1?

    中国山东
    回复
  • 龙息
    龙息 游客

    r=0不就是经典生日悖论吗,23人确实过半。

    韩国
    回复
  • 夏花绚烂
    夏花绚烂 读者

    这代码跑起来倒是挺快,就是公式看着眼晕。

    中国山西
    回复
  • 袋鼠
    袋鼠 游客

    之前搞过类似计算,阶乘太大不用log根本存不下

    中国天津
    回复
  • 樱花铃音
    樱花铃音 读者

    求问这个log转换是不是必须的?直接算会炸吗?

    中国山东
    回复
  • 尘梦
    尘梦 读者

    对数防溢出,写代码时这招挺常用

    法国
    回复
    • 众声喧哗
      众声喧哗 读者

      确实,防溢出必备

      美国@ 尘梦
      回复
  • 微风细雨
    微风细雨 读者

    直接用对数处理大数,这法子挺巧的

    中国广东
    回复
    • 云隐清风
      云隐清风 读者

      确实,避免溢出的好办法

      中国台湾@ 微风细雨
      回复
  • 布丁云
    布丁云 读者

    对数方法防溢出挺实用的

    中国山东
    回复
  • 小雪球
    小雪球 读者

    代码排版可以再优化下

    中国福建
    回复
    • Bella贝拉
      Bella贝拉 读者

      同感,看着有点乱

      中国北京@ 小雪球
      回复
  • 量子迷雾
    量子迷雾 读者

    对数变换这思路不错

    印度
    回复
  • 京剧情深
    京剧情深 读者

    算得挺快,结果一目了然

    中国江苏
    回复
  • 幻夜琉璃
    幻夜琉璃 读者

    这个公式推导过程能展开讲讲吗?

    中国江苏
    回复
  • 霜降寒夜
    霜降寒夜 读者

    对数计算这块写得蛮清楚

    中国上海
    回复
    • 星空下的梦
      星空下的梦 读者

      对,用对数处理确实清晰

      美国@ 霜降寒夜
      回复
  • 烽火使
    烽火使 读者

    概率论作业刚好用上了,帮大忙了!

    英国
    回复
  • 银月法师
    银月法师 读者

    对数处理防溢出这招挺实用

    巴基斯坦
    回复
    • 白绫吊死鬼
      白绫吊死鬼 读者

      确实,处理大数时常用这招

      美国@ 银月法师
      回复
  • 懒人日记本
    懒人日记本 读者

    M1芯片上试了,跑得飞快,没问题。

    马来西亚
    回复
  • 动如脱兔的你
    动如脱兔的你 游客

    这结果说明生活中很多“巧合”其实概率挺高的?

    日本
    回复
  • 晨曦笔记
    晨曦笔记 游客

    完全看不懂,就当看个热闹吧。

    马来西亚
    回复
  • LunarLullaby
    LunarLullaby 读者

    之前写作业也卡在这题,用对数转换是标准解法了。

    韩国
    回复
  • 灵异侦探
    灵异侦探 游客

    变量名起得也太随意了,up和dr完全猜不出意思。

    中国湖北
    回复
  • 弯酸
    弯酸 游客

    这代码跑起来快吗?会不会有性能瓶颈?

    中国山东
    回复
  • 月影谣
    月影谣 游客

    r=2的概率高得有点吓人,现实里真这么准?

    中国上海
    回复
  • 跳跃的小鸡
    跳跃的小鸡 读者

    用log算阶乘确实巧妙,避免了溢出问题。

    新西兰
    回复
  • 星旅者
    星旅者 游客

    range边界确实容易写错,debug了好几次。

    中国广东
    回复
  • 星爵彼得
    星爵彼得 游客

    之前也卡在阶乘计算上,加个log确实管用

    孟加拉
    回复
  • 胡杨林间
    胡杨林间 读者

    r=2时50人概率接近1?这也太吓人了

    中国青海
    回复
  • 诚实的镜子
    诚实的镜子 游客

    GitHub链接啥时候公开?想跑跑看

    日本
    回复
  • GoldenGaze
    GoldenGaze 游客

    23个人就过半概率?比想象中少多了

    中国江苏
    回复
  • 小猪猪猪
    小猪猪猪 读者

    吃个瓜,数学渣表示完全看不懂🍉

    中国江苏
    回复
  • DewStrider
    DewStrider 游客

    变量名up和dr是啥意思?太抽象了

    中国江苏
    回复
  • 幽冥烛阴
    幽冥烛阴 读者

    用log确实稳,之前算阶乘内存炸过好几次

    中国广东
    回复
  • 玄影梦
    玄影梦 游客

    这公式看着头大,不过代码实现倒是挺巧妙的😂

    中国江苏
    回复