Paradoja del cumpleaños

De Wikipedia, la enciclopedia libre

El problema del cumpleaños, también llamado paradoja del cumpleaños, establece que de un conjunto de 23 personas, hay una probabilidad del 50,7% de que al menos dos de ellas cumplan años el mismo día. Para 57 o más personas la probabilidad es mayor del 99,166%. En sentido estricto esto no es una paradoja ya que no es una contradicción lógica; sin embargo, es una verdad matemática que contradice la intuición común. Mucha gente piensa que la probabilidad es mucho más baja, y que hacen falta muchas más personas para que se alcance la probabilidad del 99,166%.

En teoría de la probabilidad, el problema del cumpleaños plantea la probabilidad de que, en un conjunto de n personas elegidas al azar, al menos dos compartan cumpleaños.

La paradoja del cumpleaños es una paradoja verídica: a primera vista parece errónea, pero en realidad es cierta. Aunque pueda parecer sorprendente que sólo se necesiten 23 individuos para alcanzar una probabilidad del 50% de un cumpleaños compartido, este resultado se hace más intuitivo si se considera que las comparaciones de cumpleaños se harán entre todas las parejas posibles de individuos. Con 23 individuos, hay

23 × 22 / 2 = 253 pares a considerar, mucho más de la mitad del número de días de un año.

Las aplicaciones del problema del cumpleaños en el mundo real incluyen un ataque criptográfico llamado ataque del cumpleaños, que utiliza este modelo probabilístico para reducir la complejidad de encontrar una colisión para una función hash, así como para calcular el riesgo aproximado de que exista una colisión hash dentro de los hashes de un determinado tamaño de población.

El problema se atribuye generalmente a Harold Davenport en torno a 1927, aunque no lo publicó en su momento. Davenport no afirmó ser su descubridor "porque no podía creer que no se hubiera planteado antes". La primera publicación de una versión del problema del cumpleaños fue de Richard von Mises en 1939.[1][2]

Estimación de la probabilidad[editar]

Calcular esta probabilidad es el problema del cumpleaños. La teoría fue descrita en American Mathematical Monthly en 1938 en la teoría de Estimación del total de población de peces en un lago de Zoe Emily Schnabel, bajo el nombre de captura-recaptura estadística.[3]

La clave para entender la paradoja del cumpleaños es pensar que hay muchas posibles parejas que cumplan años el mismo día. Específicamente, entre 23 personas, hay 23×22/2 = 253 pares, y cada uno es candidato potencial para cumplir la paradoja. Esto no significa que si una persona entrase en una habitación con 22 personas, la probabilidad de que cualquiera cumpla años el mismo día que quien entra, es del 50%. Es mucho más baja. Esto se debe a que ahora solo hay 22 pares posibles. El problema real de la paradoja del cumpleaños consiste en preguntar si el cumpleaños de cualquiera de las 23 personas coincide con el cumpleaños de alguna de las otras personas.

Calcúlese la probabilidad de que, en una habitación con n personas, al menos dos cumplan años el mismo día, desechando los años bisiestos y las personas gemelas, y asumiendo que existen 365 cumpleaños que tienen la misma probabilidad. Un método es calcular primero la probabilidad de que ninguna persona cumpla años el mismo día que otra, la cual viene dada por

porque la segunda persona no puede tener el mismo cumpleaños que el primero (364/365), la tercera persona no puede tener el mismo cumpleaños que las dos primeras (363/365), etc. Usando notación factorial, puede ser escrita como

Ahora, 1 - p es la probabilidad de que al menos dos personas tengan el mismo día de cumpleaños. Para n = 23 se obtiene una probabilidad de alrededor de 0,507.

En contraste, la probabilidad de que cualquiera en una habitación de n personas (excluido Ud.) tengan el mismo día de cumpleaños que usted está dada por

que para n = 22 solo da alrededor de 0,059, y se necesitaría al menos una n de 253 para dar un valor superior a 0,5.

La solución se puede generalizar para incluir a los nacidos un 29 de febrero, naturalmente de un año bisiesto. Es una solución, puede haber otras, la ventaja de ésta es que es exacta y sencilla. Se usa el algoritmo que figura más arriba (con 365, haya personas nacidas en años bisiestos o no) con los siguientes cambios:

Sean nb las personas presentes que cumplen años el 29 de febrero.

Si nb=0; Aplicar Algoritmo. FIN

Si nb=1; n=n-1; Aplicar Algoritmo. FIN

Si nb>1; hay al menos 2 personas con la misma fecha de cumpleaños. FIN

Programas informáticos[editar]

Los siguientes programas calculan las probabilidades desde 1 hasta 100:

C[editar]

#include <stdio.h>
#include <stdlib.h>
 
#define MAX_VALUE 100000

int calculate(int people_n) {

   double n = 1;
   
   for(int i = 0 ; i < people_n ; i++)
      n = n * (365 - i) / 365;
      
   n = 100 * (1 - n);
   
   return n;
   
}
 
int main(int argc, char *argv[]) {

    int group_n;
    int percentage;
    
    if(argc < 2) {
    
        printf("Usage: %s <people>\n", argv[0]);
        return 0;
        
    }

    group_n = atoi(argv[1]);
    
    if(group_n < 0 || group_n > MAX_VALUE)
        return 1;
        
    percentage = calculate(group_n);

    printf("La probabilidad de que en un grupo de %d personas, dos cumplan años el mismo día es de un %d%%.\n", group_n, percentage);
    
    return 0;
    
}

Javascript[editar]

let p = 1.0

for (let i = 1; i <= 100; i++) {
    p = p * (366 - i) / 365
    console.log(`${i}: ${1 - p}`)
}

Ruby[editar]

pr = 1.0
1.upto(100) do |i|
  pr = pr * (366 - i) / 365
  puts "#{i}: #{1 - pr}"
end

Go[editar]

package main

import "fmt"

func main() {
  p := 1.0
  for i := 1; i <= 100; i++ {
    p = p * (366 - float64(i)) / 365
    fmt.Println(i, ":", 1 - p)
  }
}

Rust[editar]

fn main() {
    probabilidad_dos_personas_cumplen_mismo_dia(100);
}

fn probabilidad_dos_personas_cumplen_mismo_dia(numero_personas: u32) {
    let mut probabilidad = 1.0;

    for i in 1..(numero_personas + 1) {
        let i = i as f32;
        probabilidad = probabilidad * (366.0 - i) / 365.0;
        let procentaje = 100.0 * (1.0 - probabilidad);
        println!("Para un grupo de {} personas, la probabilidad de que dos personas cumplan años el mismo día es del {}%",
        i, procentaje);
    }
}

Julia[editar]

println("Número de personas : Probabilidad")
p = 1
for i in 1:100
    p = p * (366 - i) / 365
    @printf("%d : %10.6f\n",i,1-p)
end

Pascal[editar]

Program Cumples ;
Var
   i : Integer ;
   p : Real ;
Begin
   writeln(' Num  -  Probabilidad') ;
   p := 1.0 ;
   For i := 1 to 100 Do
   Begin
      p := p * (366 - i) / 365 ;
      write(i:3,100*(1-p):17:6) ;
      readln ;
   End ;
End.

Python[editar]

print('Num. probabilidad')
p = 1
for i in range(1, 80):
    p = p * (366 - i) / 365
    print(f'{i}: {(1-p):.3f}')

Perl[editar]

print ('Num. probabilidad');
my $p = 1.0;
foreach( 1..100 ) {
        $p = $p * (366 - $_) / 365;
        print $_, ' : ', 1-$p, "\n";
}

C++[editar]

#include <iostream>
 
using namespace std;
 
long double calcular(int personas)
{
   long double p=1;
   for(int i=0;i<personas;i++)
   {
      p=p*(365-i)/365;
   }
   p=100*(1-p);
   return p;
}
 
int main() 
{
  int grupo;
  long double probabilidad;
  cout << "Introduce cuántas personas tiene el grupo : ";
  cin >> grupo;
  probabilidad = calcular(grupo);
  cout << "La probabilidad de que en un grupo de " << grupo << " personas, dos cumplan años el mismo día es de un " << probabilidad
  << "%" << endl;
  return 0;
}

C#[editar]

El siguiente programa calcula las probabilidades dependiendo del número de personas (grupo):

        static void Main(string[] args)
        {
            Console.WriteLine("Introduce el número de personas: ");
            int num = Convert.ToInt32(Console.ReadLine());
            Cumple(num);
            Console.Read();
        }
        static void Cumple(int num)
        {
            double p = 1.0;
            for (int i = 1; i <= num; i++)
            {
                p = p * (366 - i) / 365; //Formula de cumpleaños
            }
            Console.WriteLine(100*(1 - p));
        }

Java[editar]

El siguiente programa calcula las probabilidades dependiendo del número de personas (grupo):

import java.util.Scanner;

public class ProblemaDelCumpleanos {
    public static void main(String[] args) {
        Scanner entrada = new Scanner(System.in);
        System.out.println("Introduce el número de personas: ");
        int tamanoDePoblacion = (entrada.nextInt());
        System.out.println(cumple(tamanoDePoblacion));
        entrada.next();
    }

    /**
     * @param num Tamaño de la poblacion usada para calcular la probabilidad.
     * @return Probabilidad entre la poblacion haya 2 personas que tengan el
     * mismo cumpleaños.
     */

    public static double cumple(int num) {
        double probabilidad = 1.0;

        for (int i = 1; i <= num; i++) {
            probabilidad = probabilidad * (366 - i) / 365;
        }

        return (100 * ((1 - probabilidad)));
    }
}

PHP[editar]

function paradoja($grupo){
  $p = 1.0;			
  for ($i = 1; $i < $grupo; $i++){
    $p = $p * (366-$i) / 365;		
  }	
  $p = 1.0 - (1.0 * $p * (366-$i) / 365);
  return $p;
}  
echo paradoja(NUMERO);

PL/SQL[editar]

El siguiente programa tiene en cuenta los años bisiestos (es decir, se requieren 367 personas para garantizar una probabilidad del 100%).

Calcula todas las probabilidades desde n=1 hasta n=367 personas.

Nótese que debido al límite de decimales que PL/SQL puede manejar, si el número de personas es superior a n=227 (probabilidad 99,99999999999999999999999999999999999999%), entonces PL/SQL redondea la probabilidad al 100%.

SET SERVEROUTPUT ON

DECLARE
  P REAL := 1;
  I INTEGER;

BEGIN
  FOR I IN 1..367
  LOOP
        P := P * (367-I) / 366;    
        DBMS_OUTPUT.PUT_LINE ('Para n=' || I || ': Probabilidad ' || 100*(1-P) || '%');    
  END LOOP;
END;

MATLAB[editar]

%Script_Cumple_v3
%incluye bisiestos
clc,clear,close all,format compact,format short
disp('Num : Probabilidad')
prob=1;
for loop=1:367
    prob=prob*(367-loop)/366;
    fprintf('%3.0f : %6.4f \n', loop, 1-prob)
    if (1-prob<0.99)
      plot(loop,1-prob,'*');
      hold on
    end
end
hold off
grid on
title('Probabilidad que en un grupo, dos personas el mismo día cumplan años')
xlabel('Número de personas en el grupo')
ylabel('Probabilidad')

Microsoft SQL Server[editar]

La siguiente consulta calcula las probabilidades dependiendo del número de @Personas

DECLARE @Personas INT

SET @Personas = 23;

WITH TBL AS (
    SELECT 1 i, cast(1 as real) p
    UNION ALL
    SELECT i+1, cast((365-i)/365.0 as real)
    FROM TBL
    WHERE i < @Personas
)
SELECT (1-exp(sum(log(p))))*100 Probabilidad
FROM TBL
OPTION (MAXRECURSION 0)

R[editar]

total=1; 
for(i in 1:100) { 
  total=total*((366-i)/365)
  cat("La probabilidad de que en un grupo de ", i, " personas, al menos dos cumplan años el mismo día es de: ", 1-total,"\n")
}

Scala[editar]

object ProblemaDelCumpleanos {

   def cumple(n: Int) : Double = {
     (1 to n).foldLeft(1.0)((prob, i) => prob * (366 - i)/365.0)
   }

   def main(args: Array[String]) : Unit = {
      val personas = 25
      println(s"La probabilidad de que en un grupo de $personas personas, al menos dos de ellas cumplan años el mismo día es: ${cumple(personas)}")
   }
}

Swift[editar]

func cumple(grupo: Int) -> Double {
    var p:Double = 1
    if grupo > 1 {
        for i in 1...grupo {
            p = p * Double(366-i)/365.0
        }
    }
    return 1-p
}

let personas: Int = 25
let porcentaje: Double = cumple(grupo: personas) * 100

print("La probabilidad de que en un grupo de \(personas) personas, existan dos personas que cumplan el mismo dia es de \(porcentaje)%");

Referencias[editar]

  1. Internet Archive, Isidore Jacob (1950). Probability and the weighing of evidence. London, C. Griffin. Consultado el 8 de marzo de 2023. 
  2. P. Diaconis, F. Mosteller: Methods for Studying Coincidences. En: Journal of the American Statistical Association. 84, 4, P. 853–861.
  3. Knuth, Donald E. (1997). The Art of Computer Programming. Volume 3: Sorting and Searching (2. edición). Addison-Wesley. p. 513. ISBN 978-0-201-89685-5.