Bonjour,
Il peut parfois arriver que l'on ait besoin de générer aléatoirement des nombres aléatoires suivant une loi gaussienne, je fais donner l'algorithme basé sur la technique de Box-Muller.
Tout d'abord, on suppose que l'on dispose d'une fonction Aleatoire0-1 permettant de générer aléatoirement des réels entre 0 et 1 strictement. (par exemple Math.random de Java si je ne m'abuse).
Si vous ne disposez pas d'une telle fonction, alors vous disposez surement d'une fonction (du genre rand) qui permet de générer un entier aléatoire quelconque.
Pour simuler la fonction Aleatoire0-1, il est possible d'écrire :
A présent, on peut générer un nombre aléatoire suivant une loi gaussienne d'espérance mean et de variance sigma²
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 fonction Aleatoire0-1() -> réel { /*on choisi un entier entre 1 et un nombre très grand (par exemple 65001) Entier i = rand() % 65000+1; /*on divise par 65001 pour avoir un réel entre 0 et 1 strictement*/ Reel f = i / 65001; retourner f }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 fonction gaussienne(Réel sigma, Réel mean) Réel u1 = Aleatoire0-1(); Réel u2 = Aleatoire0-1(); retourner(racine(-2 * ln(u1)) * cos( 2 * pi * u2) * sigma + mean }
L'implémentation de Java propose le code suivant (on en parle après) (code sous licence GPL) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 synchronized public double nextGaussian() { // See Knuth, ACP, Section 3.4.1 Algorithm C. if (haveNextNextGaussian) { haveNextNextGaussian = false; return nextNextGaussian; } else { double v1, v2, s; do { v1 = 2 * nextDouble() - 1; // between -1 and 1 v2 = 2 * nextDouble() - 1; // between -1 and 1 s = v1 * v1 + v2 * v2; } while (s >= 1 || s == 0); double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s); nextNextGaussian = v2 * multiplier; haveNextNextGaussian = true; return v1 * multiplier; } }
Partager