c++ - numeros - Generar número aleatorio con densidad no uniforme
como se generan numeros aleatorios en c (5)
Debe indicar qué distribución necesita. Básicamente, usas el inverso de la función de probabilidad que deseas. Por ejemplo, la forma más común de obtener una distribución normal es la transformación Box-Muller .
Aquí está el código para Box-Muller solo para obtener la idea:
float box_muller(float m, float s) /* normal random variate generator */
{ /* mean m, standard deviation s */
float x1, x2, w, y1;
static float y2;
static int use_last = 0;
if (use_last) /* use value from previous call */
{
y1 = y2;
use_last = 0;
}
else
{
do {
x1 = 2.0 * ranf() - 1.0;
x2 = 2.0 * ranf() - 1.0;
w = x1 * x1 + x2 * x2;
} while ( w >= 1.0 );
w = sqrt( (-2.0 * log( w ) ) / w );
y1 = x1 * w;
y2 = x2 * w;
use_last = 1;
}
return( m + y1 * s );
}
¿Alguien sabía cómo generar números aleatorios con una densidad no uniforme?
En tu comentario en la pregunta:
1/sqrt(2*pi) * e^(-x^2)
La única variable es x. x en sí tendrá una densidad uniforme. Así que solo elige un buen número al azar, luego pégalo en esa ecuación.
Use un RNG de densidad uniforme y pase su resultado a través de una función de mapeo para convertirlo a su distribución de densidad deseada.
Esta clase toma una distribución como matriz (cada fila es un par de un número y su frecuencia) y genera números aleatorios. Entonces puedes mirar el método principal y ejecutar.
public class RandomGenerator {
HashMap<Integer,Range> mappa = new HashMap<Integer,Range>();
Random random = new Random();
int max;
public static void main(String as[]){
int[][] matrice = new int[3][2];
//number 5 occurs 5 times
matrice[0][0] = 5 ;
matrice[0][1] = 5 ;
//number 18 occurs 18 times
matrice[1][0] = 18 ;
matrice[1][1] = 18 ;
//number 77 occurs 77 times
matrice[2][0] = 77 ;
matrice[2][1] = 77 ;
RandomGenerator randomGenerator = new RandomGenerator(matrice);
for (int i = 0; i < 100; i++) {
System.out.println( randomGenerator.getNext() );
}
}
public int getNext(){
int percentile = random.nextInt(max);
Range r =mappa.get(percentile);
return r.getValMax();
}
public HashMap<Integer, Range> getMappa() {
return mappa;
}
public void setMappa(HashMap<Integer, Range> mappa) {
this.mappa = mappa;
}
public RandomGenerator(int[][] distribuzioneOriginale ){
ArrayList<Range> listaRange = new ArrayList<Range>();
int previous = 0;
int totaleOccorrenze = 0;
for (int riga = 0; riga < distribuzioneOriginale.length; riga++) {
Range r = new Range();
r.setValMin(previous);
r.setValMax(distribuzioneOriginale[riga][0]);
r.setOccorrenze(distribuzioneOriginale[riga][1]);
totaleOccorrenze += distribuzioneOriginale[riga][1];
previous = distribuzioneOriginale[riga][0];
listaRange.add(r);
}
int indice = 0;
for (int iRange = 0; iRange < listaRange.size(); iRange++) {
Range r = listaRange.get(iRange);
int perc = (int) ( 1000* (r.getOccorrenze() / (double) totaleOccorrenze) ) ;
for (int i = 0; i < perc; i++) {
mappa.put( i + indice , r);
}
indice += perc;
}
max = indice;
}
class Range{
int valMin;
int valMax;
int occorrenze;
public int getValMin() {
return valMin;
}
public void setValMin(int valMin) {
this.valMin = valMin;
}
public int getValMax() {
return valMax;
}
public void setValMax(int valMax) {
this.valMax = valMax;
}
public int getOccorrenze() {
return occorrenze;
}
public void setOccorrenze(int occorrenze) {
this.occorrenze = occorrenze;
}
}
}
La solución más sencilla si corresponde: utilice las instalaciones aleatorias de C ++ 11 o las de Boost , que tienen muchas distribuciones no uniformes para usted.