📜  生日悖论

📅  最后修改于: 2021-05-05 01:52:48             🧑  作者: Mango

一个房间中必须有多少人才能使房间中至少两个人有相同的生日概率为100%?
答案:367(因为可能有366个生日,包括2月29日)。
上面的问题很简单。自己尝试以下问题。
一个房间中必须有多少人才能使房间中至少两个人有相同的生日的可能性达到50%?
答案:23
这个数字令人惊讶地非常低。实际上,我们只需要70个人就可以使该概率达到99.9%。
让我们讨论广义公式。
n中两个人有相同生日的概率是多少?
假设房间中两个人的生日相同的概率为P(相同)。 P(Same)可以很容易地根据P(different)进行评估,其中P(different)是所有人都有不同生日的概率。
P(相同)= 1 – P(不同)
P(不同)可以写为1 x(364/365)x(363/365)x(362/365)x…。 x(1 –(n-1)/ 365)
我们如何得到上面的表达式?
从头到尾的人可以按照以下顺序获得生日,以使所有生日都与众不同:
第一个人可以在365岁之间过生日
第二人称生日应该与第一人称生日不同
第三人的生日应该不同于前两个人的生日。
………………。
………………
第n个人的生日应该与之前考虑的(n-1)个人不同。
以上表达式的近似值
可以使用泰勒级数来近似上述表达式。
e^{x}=1+x+\frac{x^{2}}{2!}+...
提供x << 1的ex的一阶近似值:
e^{x}\approx 1+x
将此近似值应用于对p(不同)导出的第一个表达式,设置x = -a /365。因此,
\Large{e^{\frac{-a}{365}}\approx 1-\frac {a}{365}}
上面针对p(different)得出的表达式可以写成
1 x(1 – 1/365)x(1 – 2/365)x(1 – 3/365)x…。 x(1 –(n-1)/ 365)
通过将1 – a / 365的值设置为e -a / 365 ,我们得到以下结果。
\approx 1\times e^{\frac{-1}{365}}\times e^{\frac{-2}{365}}...\times e^{\frac{-(n-1)}{365}}
\approx 1\times e^{\frac{-(1+2+...+(n-1))}{365}}
\approx 1\times e^{\frac {-(n(n-1))/2}{365}}
所以,
p(相同)= 1- p(不同)
\approx 1-e^{-n(n-1)/(2 \times 365)}
给出了一个更粗略的近似值
p(相同)
\approx 1-e^{-n^{2}/(2 \times 365)}
通过对两边取Log,我们得到了相反的公式。
n \approx \sqrt{2 \times 365 ln\left ( \frac{1}{1-p(same)} \right )}
使用上面的近似公式,我们可以估计给定概率下的人数。例如,以下C++函数find()返回概率大于给定p的最小n。
执行近似公式。
以下是在给定概率下估算人数的程序。

C++
// C++ program to approximate number of people in Birthday Paradox
// problem
#include 
#include 
using namespace std;
 
// Returns approximate number of people for a given probability
int find(double p)
{
    return ceil(sqrt(2*365*log(1/(1-p))));
}
 
int main()
{
   cout << find(0.70);
}


Java
// Java program to approximate number
// of people in Birthday Paradox problem
class GFG {
     
    // Returns approximate number of people
    // for a given probability
    static double find(double p) {
         
        return Math.ceil(Math.sqrt(2 *
            365 * Math.log(1 / (1 - p))));
    }
     
    // Driver code
    public static void main(String[] args)
    {
         
        System.out.println(find(0.70));
    }
}
 
// This code is contributed by Anant Agarwal.


Python3
# Python3 code to approximate number
# of people in Birthday Paradox problem
import math
 
# Returns approximate number of
# people for a given probability
def find( p ):
    return math.ceil(math.sqrt(2 * 365 *
                     math.log(1/(1-p))));
 
# Driver Code
print(find(0.70))
 
# This code is contributed by "Sharad_Bhardwaj".


C#
// C# program to approximate number
// of people in Birthday Paradox problem.
using System;
 
class GFG {
      
    // Returns approximate number of people
    // for a given probability
    static double find(double p) {
          
        return Math.Ceiling(Math.Sqrt(2 *
            365 * Math.Log(1 / (1 - p))));
    }
      
    // Driver code
    public static void Main()
    {        
    Console.Write(find(0.70));
    }
}
  
// This code is contributed by nitin mittal.


PHP


Javascript


C
#include
int main(){
 
    // Assuming non-leap year
    float num = 365;
 
    float denom = 365;
    float pr;
    int n = 0;
    printf("Probability to find : ");
    scanf("%f", &pr);
 
    float p = 1;
    while (p > pr){
        p *= (num/denom);
        num--;
        n++;
    }
 
    printf("\nTotal no. of people out of which there "
          " is %0.1f probability that two of them "
          "have same birthdays is %d ", p, n);
 
    return 0;
}


输出 :

30

来源:
http://en.wikipedia.org/wiki/Birthday_problem
应用范围:
1)生日悖论通常通过散列进行讨论,以表明即使对于一小组键,冲突处理也很重要。
2)生日袭击
下面是C语言的替代实现:

C

#include
int main(){
 
    // Assuming non-leap year
    float num = 365;
 
    float denom = 365;
    float pr;
    int n = 0;
    printf("Probability to find : ");
    scanf("%f", &pr);
 
    float p = 1;
    while (p > pr){
        p *= (num/denom);
        num--;
        n++;
    }
 
    printf("\nTotal no. of people out of which there "
          " is %0.1f probability that two of them "
          "have same birthdays is %d ", p, n);
 
    return 0;
}