首页 > 其他分享 >使用概率分析与指示器随机变量解决生日悖论问题及C代码示例

使用概率分析与指示器随机变量解决生日悖论问题及C代码示例

时间:2024-03-21 23:32:22浏览次数:27  
标签:概率 指示器 示例 365 生日 概率分析 随机变量 悖论

概率分析与指示器随机变量解决生日悖论问题

一、引言

在日常生活中,我们经常会遇到一些与概率相关的问题,其中生日悖论就是一个非常有趣且典型的例子。生日悖论指的是在一个随机选取的人群中,至少存在两个人生日相同的概率会随着人数的增加而迅速增长,即使当人数相对较少时,这个概率也会比人们直观感受的要高得多。这个现象之所以被称为“悖论”,是因为它与人们的直觉相悖,许多人会错误地认为需要很多人才能有较高的概率出现生日相同的情况。

本文将通过概率分析和指示器随机变量的方法,深入探讨生日悖论问题,并揭示其背后的数学原理。
在这里插入图片描述

二、生日悖论的概率分析

要理解生日悖论,我们首先需要计算在给定人数下至少存在两个人生日相同的概率。设随机选取的n个人中,每个人的生日是独立的,并且一年有365天(为简化计算,我们忽略闰年)。

计算所有人生日都不同的概率
首先,我们计算n个人生日都不同的概率。第一个人的生日可以是365天中的任意一天,概率为1;第二个人的生日与第一个人不同的概率为364/365(因为第一个人的生日已经占据了一天);第三个人的生日与前两个人都不同的概率为363/365;以此类推,第n个人的生日与前n-1个人都不同的概率为(365-n+1)/365。因此,n个人生日都不同的概率为:

P(所有人生日都不同) = 1 * (364/365) * (363/365) * … * (365-n+1)/365

这个概率随着n的增加而迅速减小。

计算至少存在两个人生日相同的概率
至少存在两个人生日相同的概率则是1减去所有人生日都不同的概率:

P(至少两人生日相同) = 1 - P(所有人生日都不同)

当n=23时,P(至少两人生日相同)大约等于0.507,这意味着在一个随机选取的23人群体中,存在至少两个人生日相同的概率超过了50%。这个结果出乎许多人的意料,因为直觉上我们会认为需要更多的人才能达到这么高的概率。

三、指示器随机变量解决生日悖论问题

为了更深入地理解生日悖论,我们可以使用指示器随机变量来进行概率分析。指示器随机变量是一个取值为0或1的随机变量,用于表示某个事件是否发生。在这个问题中,我们可以为每一对不同的人定义一个指示器随机变量Xij,如果第i个人和第j个人的生日相同,则Xij=1;否则,Xij=0。

定义指示器随机变量
对于任意一对不同的人(i, j),我们定义指示器随机变量Xij如下:

Xij = { 1, 如果第i个人和第j个人的生日相同
0, 如果第i个人和第j个人的生日不同 }

由于每个人的生日是独立且均匀地分布在365天中,所以Xij=1的概率是1/365。

计算期望
接下来我们计算所有Xij的和,即X = Σ Xij。X的值表示存在生日相同的对数。由于任意两个人生日相同的事件是互斥的(即不可能同时有三个人生日相同而只计算一次),因此X的期望值E[X]是每一对(i, j)的Xij期望值之和:

E[X] = Σ E[Xij] = Σ (1/365) = C(n, 2) * (1/365),其中C(n, 2)表示从n个人中选取2个人的组合数。

根据期望的线性性质,E[X]是Xij期望的简单累加。当E[X] > 1时,意味着存在至少一对人生日相同的概率大于50%。通过解这个不等式,我们可以找到使得至少存在一对生日相同的人的最小n值。实际上,当n=23时,E[X]约等于1.17,这与我们之前通过直接计算得到的概率相吻合。

概率与期望的关系
在这里,我们利用了期望与概率之间的紧密联系。期望是概率的加权平均,它提供了一种计算随机变量可能取值的平均数的方法。在生日悖论问题中,我们通过计算指示器随机变量的期望来估计至少存在一对生日相同的人的概率。这种方法不仅简化了计算过程,还提供了更直观的理解方式。

四、C代码实现

下面是一个使用C语言编写的程序,用于模拟生日悖论问题并计算在给定人数下至少存在两个人生日相同的概率。

c
#include <stdio.h>  
#include <stdlib.h>  
#include <time.h>  
  
#define DAYS_IN_YEAR 365  
#define MAX_PEOPLE 100  
#define TRIALS 100000  
  
int main() {  
    int people, trial, count = 0;  
    double probability;  
    srand(time(NULL)); // 初始化随机数生成器  
  
    printf("请输入人数(1-%d):", MAX_PEOPLE);  
    scanf("%d", &people);  
  
    if (people <= 0 || people > MAX_PEOPLE) {  
        printf("人数输入错误!\n");  
        return 1;  
    }  
  
    for (trial = 0; trial < TRIALS; trial++) {  
        int birthdays[DAYS_IN_YEAR] = {0}; // 记录每天是否有人生日  
        int i, duplicate = 0; // duplicate标志用于判断是否出现重复生日  
  
        for (i = 0; i < people; i++) {  
            int birthday = rand() % DAYS_IN_YEAR; // 随机生成一个人的生日  
            if (birthdays[birthday] == 1) { // 如果这个人的生日已经出现过,则标记为重复生日并跳出循环  
                duplicate = 1;  
                break;  
            } else {  
                birthdays[birthday] = 1; // 记录这个人的生日  
            }  
        }  
  
        if (duplicate == 1) { // 如果出现重复生日,则计数加1  
            count++;  
        }  
    }  
  
    probability = (double)count / TRIALS; // 计算至少存在两个人生日相同的概率  
    printf("在%d人中至少存在两个人生日相同的概率为:%.4f\n", people, probability);  
  
    return 0;  
}

这段代码首先通过用户输入确定要模拟的人数,然后进行多次试验(这里设置为100000次),在每次试验中随机生成每个人的生日并检查是否存在重复生日。最后根据出现重复生日的试验次数计算至少存在两个人生日相同的概率。需要注意的是,由于使用了随机数生成器来模拟生日的分布,因此每次运行程序得到的结果可能会有所不同,但当试验次数足够多时,结果应该接近理论概率。

五、结论与启示

通过概率分析和指示器随机变量的方法,我们深入探讨了生日悖论问题并揭示了其背后的数学原理。生日悖论之所以与人们的直觉相悖,是因为人们往往忽视了组合数的快速增长以及概率的累积效应。当人数增加时,尽管每个人生日相同的概率很小(1/365),但由于组合数的增加,至少存在一对生日相同的人的概率会迅速增长。

这个问题不仅有趣而且具有实际应用价值。例如,在密码学中,生日悖论被用于评估哈希函数的安全性;在统计学中,它提醒我们在进行数据分析时要小心处理小概率事件;在日常生活中,它也可以帮助我们更好地理解概率和随机性。

总之,通过概率分析和指示器随机变量的方法解决生日悖论问题不仅加深了我们对概率论的理解,还为我们提供了一种新的思考问题和解决问题的方法。

标签:概率,指示器,示例,365,生日,概率分析,随机变量,悖论
From: https://blog.csdn.net/lzyzuixin/article/details/136923925

相关文章

  • 开源一个教学型分库分表示例项目 shardingsphere-jdbc-demo
    在笔者心中,消息队列,缓存,分库分表是高并发解决方案三剑客。分库分表之所以被广泛使用,因为工程相对简单,但分库分表并不仅仅是分片,还是需要考虑如何扩缩容(全量同步、增量同步、数据校验等)。因此笔者做了一个教学型分库分表示例项目,计划将分库分表的技术体系都实际演示一遍。ht......
  • vue2/3 - element表格组件el-table实现懒加载树型(上下级)数据、默认展开和隐藏层级,支
    效果图在vue2、vue3项目开发中,使用element饿了么组件库,实现Table表格组件动态懒加载表格数据,可以决定是否自动展开所有2级或3级,也可以点击加载下级数据,可搭配表格的增删改查,数据变化后自动更新列表不会破坏树状的展开和折叠结构。提供详细示例代码,一键复制运行查看效果,稍......
  • 魔兽世界LUA插件开发与示例
    魔兽世界LUA插件开发1.创建插件1.1创建插件文件夹打开WorldofWarcraft\Interface\AddOns文件下,在该文件夹下创建一个插件名文件夹用来存放插件,如Makubex1.2创建插件文件在该文件夹下创建俩个文件,一个是用来给魔兽世界引入的toc头文件,一个是你自己的lua脚本文......
  • ThreadLocal详解及用法示例
    ThreadLocal概念ThreadLocal 是Java并发包(java.util.concurrent)中提供的一个类,它的主要作用是在多线程环境下为每个线程提供一个独立的变量副本,使得每个线程在访问 ThreadLocal 时获取到的都是自己的私有变量,而不是共享的同一个变量。换句话说,ThreadLocal 能够隔离线程间......
  • gRPC简单示例
    gRPC概述gRPC是一种跨语言的RPC框架,之所以它能跨语言,是因为它基于protobuf描述对象实体和方法,最后通过protobuf编译器生成指定语言的代码。这样,就能通过一套protobuf声明生成多种语言的相同API,对于实现跨语言的RPC通信非常便利,同时也使用protobuf作为通信的序列化协议。如下通......
  • opengl日记10-opengl使用多个纹理示例
    文章目录环境代码CMakeLists.txt文件内容不变。fragmentShaderSource.fsvertexShaderSource.vsmain.cpp总结环境系统:ubuntu20.04opengl版本:4.6glfw版本:3.3glad版本:4.6cmake版本:3.16.3gcc版本:10.3.0在<opengl学习日记9-opengl使用纹理示例>的基础上,拓展使用多个纹......
  • Spring-AOP面相切面编程示例(有详细注释)
    前提知识Spring-IOC容器注解方式使用https://blog.csdn.net/m0_61160520/article/details/136784799?spm=1001.2014.3001.5501切点表达式https://blog.csdn.net/m0_61160520/article/details/136782885?spm=1001.2014.3001.5501案例 1.创建项目2.导入依赖<dependenci......
  • go使用HTTP代理和SOCKS5代理的代码示例
    本文档为获取到代理IP后使用代理的代码样例,供开发者参考。代码样例直接运行无法得到正确的结果,因为代码中的代理地址/端口和应用账号密码等信息都是虚构的,您替换成自己真实的就可以正常运行了。如何获取代理地址/端口和设置代理授权?请参考:接入指南-快速入门使用前提:......
  • tokenizer分词器中的BPE分词方法的原理、样例、代码示例
    BytePairEncoding(BPE):想象一下你正在玩一种叫做“文字乐高”的游戏。在这个游戏中,你有很多小块,每个小块上写着一个字母或汉字。你的任务是用这些小块来构建单词或句子。开始时,你只能用单个字母或汉字的小块。但是游戏规则允许你找出那些经常一起出现的字母或汉字对,然后把它......
  • 通过FactoryMethod创建对象示例
    factory-bean:指定使用哪个工程实例,实例工厂,非静态方法创建beanfactory-method:指定使用哪个工厂实例的方法。静态工厂,静态方法创建bean判断的依据是创建bean的方法是否存在static修饰符。具体code如下:packagecom.gientech.factoryMethod;publicclassPerson{pr......