viernes, 12 de febrero de 2016

Crear una distribución normal en C

En el siguiente programa vamos a estudiar la generación de distribuciones de probabilidad distintas a la uniforme, haciendo uso del comando rand de C. (Aquí la publicación donde se muestra como hacerlo)
C nos permite generar variables aleatorias, sin embargo, estas siguen unicamente una ley de distribución unifrme.  Sin embargo, podemos obtener cualquier otro tipo de distribución, por ejemplo la normal, que es la más ampliamente utilizada, ya que está presente en gran cantidad de fenómenos naturales.
Partiendo del Teorema del limite central, el cual dice:

 "la distribución de probabilidad de la suma de N valores de variables aleatorias Xi independiente pero idénticamente distribuidos, con medias respectivas Ei y variancias sigma^2i, se aproxima asintóticamente a una distribución normal, a medida que N se hace muy grande, y que dicha distribución tiene como media y varianzas respectivamente, a:

"
(Fuente: "Generación de valores de las variables aleatorias", Juan F. Olivares-Pacheco)

Para obtener una distribución normal normalizada (es decir, de media 0 y desviación típica 1) a partir de una uniforme podemos proceder del modo siguiente:
    -1) Generamos N muestras de una señal uniforme, con valores distribuidos entre -0.5 y 0.5, es decir, con p(x)=1, y una esperanza nula.
    -2) Creamos una nueva varible aleatoria, sumando todas las muestras. Esta nueva varaible aleatoria sigue una distribución normal, para grandes valores de N.
    -3) Realizamos estos dos pasos M veces, de modo que podamos verificar que efectivamente se sigue una distribución normal.

El código siguiente, genera una ristra de números que siguen una distribución de media y desviación típica elegidas por el usuario. Los datos se guardan en un fichero de texto.

  /*programa que genera una serie de numeros aleatorios
que siguen una distribución normal, pidiendo al usuario
el número de datos, la varianza y la media de la distribucion,
 y los registra en un fichero .txt*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/*cK define el numero de datos que se suman para obtener
la distribucion normal. Referirse al paper de generacion de
variables aleatorias. Carpeta traitement numerique de signal*/
#define cK 1000

FILE *archivo;
int i,k,dat;
float num, media, var, desv, aux;

int main(void)
{
    /*creamos el archivo de texto*/
    archivo=fopen("prueba.txt","w");

    printf("GENERADOR DISTRIBUCION UNIFORME \n");
    printf("Seleccione la media de la distribucion: ");
    scanf("%f", &media);
    printf("Seleccione la varianza de la distribucion: ");
    scanf("%f", &var);
    printf("Seleccione el numero de datos a crear: ");
    scanf("%i", &dat);

    desv=sqrt(var);
    /*reiniciamos la semilla de generacion de numeros
    aleatorios (srand48 para generar numeros decimales)*/
    srand(time(NULL));
    for (i=1; i<=dat; i++){
        aux=0;
        for (k=1;k<=cK;k++){
            aux=aux+(float)rand()/RAND_MAX;
        }
        num=desv*sqrt((float)12/cK)*(aux-(float)cK/2)+media;
        fprintf(archivo, "%f \n", num);
    }
    fclose (archivo);
    return 0;
}

Salu10

5 comentarios: