IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Probabilités Discussion :

générer un nombre aléatoire gaussien


Sujet :

Probabilités

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 3
    Points : 2
    Points
    2
    Par défaut générer un nombre aléatoire gaussien
    Bonjour tout le monde,
    J'ai besoin de générer un nombre aléatoire gaussien entre deux valeurs (par exemple 18 et 22). Je programme en perl mais je suppose qu'une solution générique ferait l'affaire.
    Est-ce que quelqu'un pourrait m'aider sur ce point.
    Merci d'avance

  2. #2
    Invité(e)
    Invité(e)
    Par défaut
    Bonjour
    Je ne sais pas comment est la fonction randon du perl, mais partant du principe qu'elle est de répartition linéaire sur [0-1], une façon très simple d'avoir une gauissienne est la suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    f(x) : x -> valeur_moyenne + ecart * exp(1 - x²)
    Il suffit après d'appeler la fonction f en lui passant random() (enfin la fonction random du perl) comme paramètre.

    NB : pour avoir une vraie gaussienne, il faut ajouter des coefficients un peut partout : des sigma, des pi...

  3. #3
    Membre éclairé
    Avatar de Kangourou
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    579
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 579
    Points : 859
    Points
    859
    Par défaut
    salut,

    si c'est gaussien, ca restera pas forcement entre 2 valeirs : par defintiion, toute valeur meme tres grande a une proba non nulle (mais petite) d'etre choisie.

    en general, les langages donnent une fonction pour generer un nombre aleatoire avec une focntion de reparttition uniforme rentre 0 et 1 : rand, ou random.

    Pour avoir entre 18 et 22 (uniforme) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    res = 18 + rand*(22-18) ;
    Pour simuler une variable aleatoire avec une distribution gaussienne, on peut faire la somme de plusieurs variables avezc distributions uniforme. Il faut renormaliser apres pour avoir une variable centree sur 0 et reduite a l'ecart type de 1, mais ca marche pas trop mal.


    A+

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 52
    Points : 75
    Points
    75
    Par défaut
    bonjour



    la question avait déjà été posée... il y a longtemps et un lien avait été donné dans ce topic
    http://www.developpez.net/forums/vie...496&highlight= ... mais je ne sais pas ce qu'il vaut.



    Personnellement, j'adopterai la solution de Kangourou.

  5. #5
    Membre régulier
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2004
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Mars 2004
    Messages : 137
    Points : 116
    Points
    116
    Par défaut Pas d'accord !
    Citation Envoyé par mabu
    Bonjour
    Je ne sais pas comment est la fonction randon du perl, mais partant du principe qu'elle est de répartition linéaire sur [0-1], une façon très simple d'avoir une gauissienne est la suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    f(x) : x -> valeur_moyenne + ecart * exp(1 - x²)
    Il suffit après d'appeler la fonction f en lui passant random() (enfin la fonction random du perl) comme paramètre.

    NB : pour avoir une vraie gaussienne, il faut ajouter des coefficients un peut partout : des sigma, des pi...
    Ce que tu proposes n'est pas bon.

    1 - Tu ne dis même pas quelle valeur n proposer à random(n)
    2 - Quelle que soit la valeur donnée, ce n'est pas correct

    La fonction f est la courbe de probabilité. Si tu appliques f sur le résultat x de random tu obtiendras la probabilité p(x) d'une gaussienne de centre "valeur_moyenne" et d'écart-type "ecart", c'est à dire un nombre compris entre 0 et le top de la courbe de gauss. Par exemple, si tu choisis d'appeler random(5) l'application de ta fonction fournira un réel entre 0 et 0,1 qui n'a rien à voir avec des valeurs entre 0 et 5. Et si tu fournis random(5)+18 à f tu trouveras encore un nombre entre 0 et 0,1, valeur de la courbe f, qui n'a donc rien à voir avec les nombres voulus, entre 18 et 22. Tu es dans un autre univers !!!

  6. #6
    Membre régulier
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2004
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Mars 2004
    Messages : 137
    Points : 116
    Points
    116
    Par défaut Une solution
    La solution de Kangourou n'est pas bonne non plus. La somme de plusieurs variables aléatoires équiprobables n'est pas une gaussienne ; bon, c'est vrai que ça ressemble un peu, en fait ça tend vers une gaussienne quand on fait tendre le nombre de variables vers l'infini, et je ne sais pas jusqu'à quel infini il faut aller...

    J'ai une solution bien plus simple.

    1 - Calculer dans un tableau TAB les probas d'une gaussienne. Ce que dit Kangourou au sujet des limites est vrai : ça ne peut pas être une gaussienne si ça va de 18 à 22 !
    Donc, il faut choisir un écart-type raisonnable qui placerait la quasi totalité de la gaussienne à l'intérieur de l'intervalle 18 à 22. Par exemple, un écart-type de 1,5 autour de 20, garantirait que peut-être 90% des tirages seraient entre 18 et 22. Choisir la taille du tableau de manière que la précision voulue soit atteinte. Par exemple, 101 intervalles ou 1001 intervalles, disons 1001 pour l'exemple ci-dessous, représentant l'intervalle 18 à 22 : donc chaque intervalle aura la largeur
    L=(22-18 )/1001. L'intervalle i représentera la zone entre 18+i*L et
    18+(i+1)*L, le milieu de cet intervalle étant 18+(2*i+1)*L/2

    On calculera TAB[i]=f(18+(2*i+1)*L/2-20) (la soustraction de 20 revient à centrer sur la moyenne)

    la fonction f représentant la loi de probabilité de la gaussienne de moyenne 0 et d'écart-type sigma étant définie par :

    f(x)=1/(sigma*racinede(2*pi))*exp(-x*x/(2*sigma*sigma))

    2 - Sommer TAB : trouver la somme S. Diviser tous les éléments de TAB par S ; ainsi la somme de TAB sera exactement égale à 1. Cela revient à tronquer la gaussienne à gauche et à droite.

    3 - Intégrer TAB, c'est à dire remplacer TAB[i] par la somme des anciens éléments de TAB de 0 à i :

    for (i=1;i<=1000;i++)
    {
    tab[i]+=tab[i-1];
    }

    Tout cela n'est fait qu'une seule fois : c'est la préparation.

    Ensuite pour chaque tirage on appelle une fonction random qui fournit un réel x entre 0 et 1. Et on cherche la première valeur de i telle que tab[i]>x. Si on a beaucoup de tirages à faire, on pourra faire une recherche dichotomique très rapide dans ce tableau par construction ordonné.

    A i on associera enfin l'abscisse y du milieu de l'intervalle qu'il représente, soit y=18+(2*i+1)*L/2.

    Alors, la loi de probabilité de la variable y sera la loi représentée par TAB, c'est-à-dire une gaussienne tronquée à gauche et à droite.

    C'est une méthode tout-à-fait générale, je veux dire, pas seulement pour les Gaussiennes. Quelle que soit la loi de probabilité, on calcule la loi dans un tableau aussi grand que possible pour la précision voulue, on intègre le tableau puis on le norme pour avoir un tableau dont la somme est 1. Ensuite pour chaque tirage équiprobable entre 0 et 1, il suffit de trouver le point du tableau qui correspond.

  7. #7
    Membre régulier
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2004
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Mars 2004
    Messages : 137
    Points : 116
    Points
    116
    Par défaut
    En fait, mon post précédent décrit une méthode discrète pour réaliser sur ordinateur une opération qui peut être définie en continu en mathématiques.

    Si une fonction f est la loi de probabilité d'une variable x, alors ∫f(x)dx (de -∞ à +∞) = 1.

    J’appelle g l’intégrale de f : g(x)= ∫f(t)dt (de -∞ à x)

    g(-∞)=0
    g(+∞)=1

    g étant croissante (comme intégrale d’une fonction positive ou nulle) et g(x) croissant de 0 à 1 lorsque x croît de -∞ à +∞ on peut définir sa fonction réciproque reci_g sur ]0,1[

    Alors, si u est une variable aléatoire de loi de probabilité constante sur ]0,1[, x=reci_g(u) est une variable aléatoire dont la loi de probabilité est f.

    Donc, le premier calcul de TAB ci-dessus calcule f

    L’intégration de TAB calcule g

    Et la recherche du plus petit i tel que TAB[i]>x n’est autre que le calcul de reci_g(x).

  8. #8
    Invité(e)
    Invité(e)
    Par défaut Re: Pas d'accord !
    Citation Envoyé par ceugniet
    1 - Tu ne dis même pas quelle valeur n proposer à random(n)
    Si : une fonction donc la répartition est linéaire entre 0 et 1.
    2 - Quelle que soit la valeur donnée, ce n'est pas correct
    C'est juste... je me suis emmélé les pinceaux.
    J'ai simplement donné la fonction de répartition (fausse qui plus est, mea culpa)

  9. #9
    Membre éclairé
    Avatar de Kangourou
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    579
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 579
    Points : 859
    Points
    859
    Par défaut Re: Une solution
    Salut,

    Citation Envoyé par ceugniet
    Ensuite pour chaque tirage on appelle une fonction random qui fournit un réel x entre 0 et 1. Et on cherche la première valeur de i telle que tab[i]>x. Si on a beaucoup de tirages à faire, on pourra faire une recherche dichotomique très rapide dans ce tableau par construction ordonné.
    ....
    Ensuite pour chaque tirage équiprobable entre 0 et 1, il suffit de trouver le point du tableau qui correspond.
    Attention ...
    C'est vrai que ca permet de tirer des nombres avec une courbe qui se rapproche plus de la gaussienne, ou de la courbe qu'on veut.
    Mais du coup on ne tire que dans un nombre restreint de valeurs, ici 1000. Alors ca depend des applications, mais si c'est pour faire un peu de simulation, un generateur de nombre aleatoires avec seulement 1000 nombres differents, c'est pas super super ...


    Quant a la convergence vers la gaussienne d'une somme de nombre tires avec un loi uniforme, une somme de 4 termes donne deja une approximation cubique de le densite, l'erreur decroit donc assez vite.


    A+

  10. #10
    Membre régulier
    Homme Profil pro
    Retraité
    Inscrit en
    Mars 2004
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Mars 2004
    Messages : 137
    Points : 116
    Points
    116
    Par défaut Re: Une solution
    Citation Envoyé par Kangourou
    Attention ...
    C'est vrai que ca permet de tirer des nombres avec une courbe qui se rapproche plus de la gaussienne, ou de la courbe qu'on veut.
    Mais du coup on ne tire que dans un nombre restreint de valeurs, ici 1000. Alors ca depend des applications, mais si c'est pour faire un peu de simulation, un generateur de nombre aleatoires avec seulement 1000 nombres differents, c'est pas super super ...
    Je veux bien te croire, mais j'ai dit "Par exemple, 101 intervalles ou 1001 intervalles," et j'ai continué mon exemple sur 1001, mais rien n'empêche d'en faire 10000 ou même 1000000, même sur un PC, il y a de la place. Et la recherche dichotomique sera deux fois plus lente sur 1000000, mais toujours extrêmement rapide.


    Citation Envoyé par Kangourou
    Quant a la convergence vers la gaussienne d'une somme de nombre tires avec un loi uniforme, une somme de 4 termes donne deja une approximation cubique de le densite, l'erreur decroit donc assez vite.


    A+
    Sévère sur le nombre de valeurs, je te trouve bien laxiste sur une telle approximation... Mais je fais confiance à ton expérience - je ne l'ai jamais fait moi-même.

    @+

Discussions similaires

  1. Algo pour générer des nombres aléatoires
    Par Admin dans le forum Algorithmes et structures de données
    Réponses: 4
    Dernier message: 12/06/2006, 09h06
  2. Réponses: 12
    Dernier message: 10/06/2006, 23h16
  3. Réponses: 2
    Dernier message: 16/05/2006, 17h02
  4. Réponses: 16
    Dernier message: 08/03/2006, 11h18
  5. Générer un nombre aléatoire entre 0 et 1 (INCLUS !!!)
    Par haypo dans le forum Algorithmes et structures de données
    Réponses: 3
    Dernier message: 22/08/2002, 16h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo