Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

PARADOXE DES ANNIVERSAIRES


Information sur la source

Catégorie :Maths Classé sous : paradox, anniversaires, random, math, script Niveau : Débutant Date de création : 24/07/2008 Date de mise à jour : 24/07/2008 13:57:16 Vu / téléchargé: 3 815 / 107

Note :
9 / 10 - par 2 personnes
9,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (10)
Ajouter un commentaire et/ou une note

Description

Cliquez pour voir la capture en taille normale
J'hésite entre la catégorie "Math" et "VbScript" pour cette source. Il s'agit d'un script traitant du Paradoxe Des Anniversaires. J'ai choisi le VbScript parce que je n'ai rien d'autre sous la main.

TRES IMPORTANT: j'utilise WScript.Echo, donc ne lancez pas le script en double-cliquant dessus mais il faut le lancer avec CScript en ligne de commandes (voir le ScreenShot).

Le paradoxe des anniversaires énonce que: si dans une pièce, il y a au moins 23 personnes, la probabilité qu'il y a au moins deux personnes dans cette pièce qui ont leur anniversaire le même jour (même jour, même mois) est de plus de 50%. Le paradoxe est qu'il suffise de 23 personnes, ce qui parait peu, mais pourtant...
Le script en fait l'expérience en remplissant un tableau avec des valeurs au hasard et ensuite il regarde s'il y en a des identiques. Ensuite, le script calcule et affiche la proba.

J'ai commenté la source.

En espérant que vous trouverez ça intéressant...

--
MisterWhiteLapin

 

Source

  • REM Forcer la déclaration des variables.
  • Option Explicit
  • REM Pour avoir une valeure de random différente à chaque fois.
  • Randomize
  • REM Nombre de jours sur lequel porte l'expérience.
  • Const nbJours = 365.0
  • REM Nombre de jours décrémenté. 365 puis 364 puis 363 puis ...
  • REM Utilisé ici comme un type float.
  • Dim nbJoursDec
  • REM i et j. Deux variables de boucles.
  • Dim i, j
  • REM Nombre de personnes concernés.
  • Dim n
  • REM Resultat recalculé à chaque itération. Utilisé comme un type float.
  • Dim res
  • REM Un string qui sert à accumuler le résultat avant de l'afficher.
  • Dim strTemp
  • REM Tableau contenant des valeures de 0 à (nbJours - 1).
  • Dim tabRandom
  • REM #############################################################################
  • REM #############################################################################
  • REM ################## Gestion des arguments (le nombre de personnes)############
  • REM Si il n'y a pas d'argument ou que l'argument n'est pas valide,
  • REM on le met arbitrairement à 25.
  • If (WScript.Arguments.Count >= 1) Then
  • On Error Resume Next
  • n = CInt(WScript.Arguments(0))
  • If (Err.Number <> 0) Then
  • n = 25
  • End If
  • On Error Goto 0
  • Else
  • n = 25
  • End If
  • REM #############################################################################
  • REM #############################################################################
  • REM #############################################################################
  • REM #############################################################################
  • REM #############################################################################
  • REM ################## Tableau de random ########################################
  • ReDim tabRandom(n)
  • REM On initialise le tableau avec des valeures
  • REM aléatoires de 0 à (NbJours - 1) (364 dans notre cas).
  • strTemp = ""
  • i = 0
  • While (i < n)
  • tabRandom(i) = Int(nbJours * Rnd)
  • WScript.Echo "tabRandom(" & i & ") = " & tabRandom(i)
  • i = i + 1
  • WEnd
  • REM On va parcourir le tableau avec une complexité en O(n²) pour chercher les
  • REM doublons et les stocker dans la variable strTemp en vue de les afficher plus tard.
  • i = 0
  • While (i < n)
  • j = i + 1
  • While (j < n)
  • If (tabRandom(i) = tabRandom(j)) Then
  • If (strTemp = "") Then
  • strTemp = "Mêmes nombres aux indexes:" & VbCrlf
  • End If
  • strTemp = strTemp & " " & i & " et " & j & "." & VbCrlf
  • End If
  • j = j + 1
  • WEnd
  • i = i + 1
  • WEnd
  • If (strTemp = "") Then
  • strTemp = "Pas de doublon détécté." & VbCrlf
  • End If
  • REM #############################################################################
  • REM #############################################################################
  • REM #############################################################################
  • REM #############################################################################
  • REM #############################################################################
  • REM ################## Calcul de la probabilité #################################
  • REM Explication du calcul (voir wikipedia et Internet pour
  • REM plus de renseignements).
  • REM
  • REM
  • REM ###### Ici, nbJours vaut 365 (cas normal
  • REM du paradoxe des anniversaires) ######
  • REM
  • REM N.B.: Ici, 365^3 signifie 365 * 365 * 365 (c'est à dire "365 puissance 3")
  • REM
  • REM
  • REM
  • REM p_bar(n) = 1 - p(n) et p(n) = 1 - p_bar(n)
  • REM
  • REM p_bar(0) et p_bar(1): Pas de sens.
  • REM p_bar(2) = 365 * (365 - 1) / (365^2)
  • REM = 364 / 365
  • REM p_bar(3) = 365 * (365 - 1) * (365 - 2) / (365^3)
  • REM = 365 * 364 * 363 / (365^3)
  • REM = p_bar(2) * 363 / 365
  • REM p_bar(4) = 365 * (365 - 1) * (365 - 2) * (365 - 3) / (365^4)
  • REM = 365 * 364 * 363 * 362 / (365^4)
  • REM = p_bar(3) * 362 / 365
  • REM
  • REM p_bar(n) = p_bar(n - 1) * (365 - n + 1) / 365
  • If (n < 2) Then
  • WScript.Echo "Pas de sens."
  • WScript.Quit
  • End If
  • REM L'étape 1 est déjà faite car 365 / 365 = 1, on commance direct à 364 / 365.
  • res = 1.0
  • nbJoursDec = nbJours - 1.0
  • i = 1
  • While (i < n)
  • res = res * (nbJoursDec) / nbJours
  • nbJoursDec = nbJoursDec - 1.0
  • i = i + 1
  • WEnd
  • REM On vient de calculer "p bar", on le transforme donc maintenant
  • REM en p, laprobabilité qui nous intéresse.
  • res = (1.0 - res) * 100.0
  • REM #############################################################################
  • REM #############################################################################
  • REM #############################################################################
  • REM Affichage de la probabilité.
  • strTemp = strTemp & "Nombre de personnes dans la salle: " & n & VbCrlf & _
  • "Probabilité de ""au moins 2 anniversaires le même jour"": " & res & "%"
  • REM Affichage de totue la string résultat (malheuresement, c'est trop
  • REM gros pour tenir dans une MsgBox).
  • WScript.Echo strTemp
REM Forcer la déclaration des variables.
Option Explicit

REM Pour avoir une valeure de random différente à chaque fois.
Randomize

REM Nombre de jours sur lequel porte l'expérience.
Const nbJours = 365.0

REM Nombre de jours décrémenté. 365 puis 364 puis 363 puis ...
REM Utilisé ici comme un type float.
Dim nbJoursDec

REM i et j. Deux variables de boucles.
Dim i, j

REM Nombre de personnes concernés.
Dim n

REM Resultat recalculé à chaque itération. Utilisé comme un type float.
Dim res

REM Un string qui sert à accumuler le résultat avant de l'afficher.
Dim strTemp

REM Tableau contenant des valeures de 0 à (nbJours - 1).
Dim tabRandom





REM #############################################################################
REM #############################################################################
REM ################## Gestion des arguments (le nombre de personnes)############
REM Si il n'y a pas d'argument ou que l'argument n'est pas valide,
REM on le met arbitrairement à 25.
If (WScript.Arguments.Count >= 1) Then
	On Error Resume Next
	n = CInt(WScript.Arguments(0))
	If (Err.Number <> 0) Then
		n = 25
	End If
	On Error Goto 0
Else
	n = 25
End If
REM #############################################################################
REM #############################################################################
REM #############################################################################





REM #############################################################################
REM #############################################################################
REM ################## Tableau de random ########################################
ReDim tabRandom(n)

REM On initialise le tableau avec des valeures
REM aléatoires de 0 à (NbJours - 1) (364 dans notre cas).
strTemp = ""
i = 0
While (i < n)
	tabRandom(i) = Int(nbJours * Rnd)
	WScript.Echo "tabRandom(" & i & ") = " & tabRandom(i)
	i = i + 1
WEnd


REM On va parcourir le tableau avec une complexité en O(n²) pour chercher les
REM doublons et les stocker dans la variable strTemp en vue de les afficher plus tard.
i = 0
While (i < n)
	j = i + 1
	While (j < n)
		If (tabRandom(i) = tabRandom(j)) Then
			If (strTemp = "") Then
				strTemp = "Mêmes nombres aux indexes:" & VbCrlf
			End If
			strTemp = strTemp & "       " & i & " et " & j & "." & VbCrlf
		End If
		j = j + 1
	WEnd
	i = i + 1
WEnd

If (strTemp = "") Then
	strTemp = "Pas de doublon détécté." & VbCrlf
End If
REM #############################################################################
REM #############################################################################
REM #############################################################################





REM #############################################################################
REM #############################################################################
REM ################## Calcul de la probabilité #################################


REM   Explication du calcul (voir wikipedia et Internet pour
REM                          plus de renseignements).
REM   
REM   
REM   ######     Ici, nbJours vaut 365 (cas normal
REM              du paradoxe des anniversaires)   ######
REM   
REM   N.B.: Ici, 365^3 signifie 365 * 365 * 365 (c'est à dire "365 puissance 3")
REM   
REM   
REM   
REM   p_bar(n) = 1 - p(n)   et   p(n) = 1 - p_bar(n)
REM   
REM   p_bar(0) et p_bar(1): Pas de sens.
REM   p_bar(2) = 365 * (365 - 1) / (365^2)
REM            = 364 / 365
REM   p_bar(3) = 365 * (365 - 1) * (365 - 2) / (365^3)
REM            = 365 * 364 * 363 / (365^3)
REM            = p_bar(2) * 363 / 365
REM   p_bar(4) = 365 * (365 - 1) * (365 - 2) * (365 - 3) / (365^4)
REM            = 365 * 364 * 363 * 362 / (365^4)
REM            = p_bar(3) * 362 / 365
REM   
REM   p_bar(n) = p_bar(n - 1) * (365 - n + 1) / 365


If (n < 2) Then
	WScript.Echo "Pas de sens."
	WScript.Quit
End If


REM L'étape 1 est déjà faite car 365 / 365 = 1, on commance direct à 364 / 365.
res = 1.0
nbJoursDec = nbJours - 1.0
i = 1
While (i < n)
	res = res * (nbJoursDec) / nbJours
	nbJoursDec = nbJoursDec - 1.0
	i = i + 1
WEnd

REM On vient de calculer "p bar", on le transforme donc maintenant
REM en p, laprobabilité qui nous intéresse.
res = (1.0 - res) * 100.0


REM #############################################################################
REM #############################################################################
REM #############################################################################





REM Affichage de la probabilité.
strTemp = strTemp & "Nombre de personnes dans la salle: " & n & VbCrlf & _
                    "Probabilité de ""au moins 2 anniversaires le même jour"": " & res & "%"

REM Affichage de totue la string résultat (malheuresement, c'est trop
REM gros pour tenir dans une MsgBox).
WScript.Echo strTemp

Conclusion

Un petit Script VBS qui illustre le "Paradoxe des anniversaires" découvert par Richard von Mises.
Page Wikipedia: http://fr.wikipedia.org/wiki/Paradoxe_des_anniversaires

 

Fichier Zip

Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip

Historique

24 juillet 2008 13:45:08 :
Inexactitude mathématique dans l'affichage du résultat. Modification de la source et du ScreenShot.
24 juillet 2008 13:57:16 :
Il manquait le mot "moins".

Commentaires et avis

signaler à un administrateur
Commentaire de gillardg le 24/07/2008 14:08:25

dans ce genre de problème on oublie souvent les années bisextilles.
les gens qui sont nés le 29/2 ils sont punis??

signaler à un administrateur
Commentaire de MisterWhiteLapin le 24/07/2008 14:17:09


Bonjour Gillardg,

Pour le cas du 29 février, Wikipedia dit: "Le calcul exposé néglige la date du 29 février dont la prise en compte changerait très peu le pourcentage indiqué."
J'ai juste posté ça pour l'intérêt mathématique. Maintenant, si tu veux considéré le 29 févriers, tu peux modifier la source en mettre 366 à la place de 365. C'est une constante, tu n'as qu'une valeur à changer.

Je n'ai pas oublié le 23 février, c'est juste que je m'en moque complètement.


Cordialement,

--
MisterWhiteLapin

signaler à un administrateur
Commentaire de gillardg le 24/07/2008 14:29:56

c'est juste une constatation par rapport à beaucoup de calcul de statistiques sur des dates

signaler à un administrateur
Commentaire de RcrivelliNET le 25/07/2008 11:11:21 9/10

Hello,

Je n'ai pas eu le temps de regarder le code ni toute la fonction mathématique de ton code, par contre je vais quand même te mettre un 9/10 pour le bel effort de commentaire ... je pense qu'il serra execivement utile pour les débutant.

C'est le genre de petites sources simple et utile pour l'apprentissage qui fait avancer le schmilbic :-) ...

Merci.
A+

signaler à un administrateur
Commentaire de us_30 le 27/07/2008 13:15:11

Bonjour,

En quoi est-ce un paradoxe ?

C'est juste contre intuitif pour certains...

Il aurait été intéressant de plutôt faire des petites fonctions de calculs séparées, par exemple pour remplir un tableau de nombre aléatoire, pour que ce code soit en parti réutilisable dans un autre projet...

Amicalement,
Us.

signaler à un administrateur
Commentaire de MisterWhiteLapin le 28/07/2008 09:10:04


Bonjour us_30,

Je suis surpris par ta question "En quoi est-ce un paradoxe ?". Si tu as été lire la page Wikipedia comme suggéré, tu saurais que le "paradoxe des anniversaires" c'est le nom donné à "une estimation probabiliste". Ce nom a été donné par celui qui l'a énoncé Richard von Mises, pas par moi. j'ai juste proposé un code qui l'illustre.

En ce qui concerne le caractère non réutilisable de ce code, tu as raison ...
... mais mon but en postant ce code dans la catégorie "mathématiques" était avant tout d'illustrer cette célèbre découverte de Richard von Mises et pas de donner des fonctions toutes faites à réutiliser dans un projet.

Si le lecteur débutant lit ce code dépourvu d'appels à fonctions, il comprendra probablement tout le code et sera capable de se servir de manière intelligente de ce code pour faire ce qu'il cherche à faire.

Maintenant, je conçois que ce code est perfectible:
   - faire des appels à fonction,
   - utiliser des boucles for au lieu de boucles while,
   - faire moins de 80 colonnes par ligne,
   - faire des fonctions de 20 lignes maximum,
   - ...

Mais le but, c'est que tous le monde ait compris le fonctionnement du code et la notion mathématique.


Cordialement,

PS: Je viens de regarder ton profil http://www.vbfrance.com/auteur/US30/488557.aspx, j'ai du mal à croire que tu as 107 ans (et mentir: c'est pas bien) ;-)


--
MistertWhiteLapin

signaler à un administrateur
Commentaire de us_30 le 28/07/2008 11:38:33

Bonjour,

... A toute intervention, il ne faut jamais se sentir personnellement visé; du moins c'est un conseil...

Ma question "En quoi est-ce un paradoxe ?", n'a que comme réponse : "Ce nom a été donné par celui qui l'a énoncé Richard von Mises"... donc je suis en droit de me demander pourquoi appeler ce fait statistique compréhensible et expliqué grâce aux calculs des probabilités, en quoi est-ce un paradoxe... Si on commence a appeler chaque fait statistique qui surprend certaines personnes " des paradoxes ", on a pas fini... En effet, la vie est pleine de paradoxe, voir la vie elle-même est paradoxale... En effet, quelle est la probabilité qu'une planète abrite la vie ? Très faible assurément... pourtant on est là (à débattre pour presque rien). Doit-on appeler ce fait, le paradoxe de la vie ?

=

Plus sérieusement, sur le code. Si ton but premier était de donner un exemple de code pour aider les débutants, alors je reste sur ma remarque.
Montrer sur un code simple, la structure d'une fonction, la façon de les utiliser (c'est vraiment pas compliqué, en plus), etc... me semble plus intructif. C'est même sur une structure d'un exemple simple, qu'on apprend le mieux, et non dans une programmation dense, non ?
C'est d'ailleurs avec cela, que ta programmation aurait atteint son but... aider les débutants à progresser, me semble-t-il.

Avec moins de blabla, je dirais aussi à la suite de tes remarques :

Maintenant, je conçois que ce code est perfectible : " => oui, ben le code vraiment parfait n'est pas chose aisée... alors... "
   - faire des appels à fonction, " => Oui, déjà expliqué "
   - utiliser des boucles for au lieu de boucles while, " => ben, non, pas obligé. "
   - faire moins de 80 colonnes par ligne, " => NON. Pas d'accord "
   - faire des fonctions de 20 lignes maximum, " => Absolument, non. "

=

Ceci dit, je n'expose que de simples remarques personnelles, rien de plus... que mes derniers neuronnes survivant (avec mon grand âge) me sugère... et quand tu dis : "et mentir: c'est pas bien"... La vérité serait bien pire... hahaha...

Amicalement,
Us.

signaler à un administrateur
Commentaire de 33solo le 28/07/2008 11:40:07 9/10

Bonjour MisterWhiteLapin,

Très bien documenté. Je suis pas au top au niveau math et j'ai compris.

Un autre manière de voir la formule du Paradoxe ...

REM avec n = 23
REM p_bar(n)= [(nbJours)! - (nbJours - n + 1)!] / nbJours^n
REM p_bar(n)= [365!-343!]/365^23 => 1 boucle FOR pour calculer [365!-343!]
REM Avec à la place de :
REM     res = 1.0
REM     nbJoursDec = nbJours - 1.0
REM     i = 1
REM     While (i < n)
REM     res = res * (nbJoursDec) / nbJours
REM     nbJoursDec = nbJoursDec - 1.0
REM     i = i + 1
REM     WEnd

Res = 1
For i=(nbJours - n + 1) to nbJours : Res = Res * i : Next i
Res = Res / (nbJours)^n

signaler à un administrateur
Commentaire de RcrivelliNET le 28/07/2008 12:02:12

Hello à tous,

Sans lancer la polémique je ne pense pas que l'endroit soit propice au débat sur peut t'on appeler tel ou tel choses un paradoxe ... j'y ai d'ailleurs longtemps travaillé sur le sujet et nombre de philosophes s'y sont cassé les dents ... mais pour mettre un petit peut les choses en places voici en substance ce que donne la définition de "Paradoxe" :

Un paradoxe est une proposition qui contient ou semble contenir une contradiction logique, ou un raisonnement qui, bien que sans faille apparente, aboutit à une absurdité, ou encore, une situation qui contredit l'intuition commune.

Ce qui me semble totalement convenir a l'énoncé ... d'ailleurs le paradoxe est très subjectif puisque c'est le résonnement qui pousse au paradoxe tant et si bien que la vie peut être considérer comme un paradoxe ce qui est en soit un paradoxe ... donc je ne pense pas qu'il soit nécessaire d'en débattre ici.

Pour ce qui est du reste ... je reste sur mon précédent commentaire ... à savoir un code très bien documenté qui reste une mine d'or pour un débutant qui pourra faire évoluer son code en fonction de son apprentissage ... c'est quand même plus ludique qu'un "hello world"

Bonne continuation à tous.

signaler à un administrateur
Commentaire de MisterWhiteLapin le 28/07/2008 12:45:22

Bonjour 33solo,

Pour ton bout de code du calcul sur la fonction mathématique je suis tout à fait d'accord avec toi, c'est bien ça que nous voulons calculer.

Dans mon code, je n'ai pas été adepte de faire le calcul du produit "365 * 364 * 363 ..." puis, à la fin, tout diviser par une grande puissance de 365 car, selon le système sur lequel tu joues ton programme, il se peut que bien vite tu ne puisses plus mettre à la puissance. Avec ma méthode, j'évite ce problème là.

Pour ce qui est du VBScript, j'ai été très surpris: il va très loin!
Je viens de faire tourner le bout de code suivant:

for i = 0 to 1000
a = 365^i
Wscript.echo "365^" & i & " = " & a
Next

il a calculé jusqu'à 365^120. Après il lance une erreur:

...
365^117 = 6,14136827812038E+299
365^118 = 2,24159942151394E+302
365^119 = 8,18183788852588E+304
365^120 = 2,98637082931195E+307
D:\d.vbs(2, 2) Erreur d'exécution Microsoft VBScript: Dépassement de capacité



Donc si j'avais utilisé ton morceau de code dans mon script, nous n'aurions pas pu lancer le script sur plus de "120 personnes" sans avoir une erreur d'exécution. Dans la version que j'ai proposé, il arrondie assez vite la probabilité à 100% (ce qui est faux d'un point de vue mathématique) mais au moins il ne plante pas. Mais quand on est à 121, il calcul encore de manière assez précise sans arrondir à 100%.

Voilà pour l'explication de mon choix, il est vrai que cela méritait un éclaircissement puisque, au départ, je l'aurai bien écrit de la même manière que le suggère 33solo.

Cordialement,

--
MisterWhiteLapin

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

la fonction Random [ par etude euria ] Bonjour,Nous sommes des étudiants dans un institut d'actuariat.Nous avons besoin de la fonction Random pour un bureau d'études.Il faut insérer des par imprimer un fichier [ par mic ] Salutje désire ecrire un script VB qui me permétrer d'ouvrir un fichier (.rep : rapport BI Query) de l'imprimer et de le fermer asns aucune interventi script d'installation - ajout de fichiers [ par Georef ] Bonjour,lors de la génération d'un pgm d'installation, je dois ajouterde nombreux fichiers de données. La manipulation"ajouter", choix du fichier... e lancer un script Unix sur une station depuis VB sur un pc [ par OCh ] Quelqu'un peut-il me donner les grandes lignes de ce que je doisecrire en C sous Unix pour assurer un dialogue avec mon applicationVB sur pc? geometrie math [ par alien ] je cherche un max de formule math appliquee a la geometrie ex:calcul de l'intersection de deux lignes ou cercle ....merci Lancer l'exécution d'un script sur un Unix [ par sam ] Comment peut-on lancer, depuis Windows, l'exécution d'un script sur un Unix ?On m'a parler du démon RSHD sur unix et du client RSH windows ...... C Recherche d?un bouquin de math.. [ par Marc ] Bonjour,Je cherche a acquérir d´ocasion les trois tomesdu livre de Gomes Teixeira:Courbes spéciales remarquables .Il a été réedité en Fraçais aux édit Lotus Script [ par Derrick soft ] Bonjour,Je voulais savoir si certains programmeur serait intéressé par une rubrique LotusScript et formula Notes.Le LotusScript est voisin du VBA sauf random [ par debutant ] . Accès à une base Paradox [ par Robert ] Voila mon problème : je veux accéder depuis VB6 à une base de données Paradox mais l'ODBC me répond systématiquement :Pilote ISAM introuvable, erreur


Nos sponsors

Sondage...

CalendriCode

Janvier 2009
LMMJVSD
   1234
567891011
12131415161718
19202122232425
262728293031 

Consulter la suite du CalendriCode

Téléchargements

Logiciels à télécharger sur le même thème :



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel BAÏSE, Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,640 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.