Как случайным образом генерировать целые числа после определенного распределения (степенное, нормальное, пуассоновское ...) в c - PullRequest
0 голосов
/ 04 марта 2020

Я почти ничего не знаю, когда дело доходит до вероятностей и статистики, и я пытаюсь создать случайные целочисленные генераторы, следуя определенным распределениям в c.
Из того, что я собрал из википедии и вопросов, на которые уже даны ответы здесь Я написал следующие функции, которые создают массив uint64_t после этих распределений.

#define EXP 2.718281828459045



uint64_t *uniform_dist_ints(uint64_t nb_vals,uint64_t upper_bound) {
    uint64_t *arr=malloc(nb_vals*sizeof(uint64_t ));
    for(uint64_t i=0;i<nb_vals;i++)
        arr[i]=1+arc4random_uniform(upper_bound-1);//pas de 0
    return arr;
}

//from http://mathworld.wolfram.com/RandomNumber.html
uint64_t *power_dist_ints(uint64_t nb_vals,uint64_t lower_bound,uint64_t upper_bound,uint64_t p) {
    uint64_t *arr=malloc(nb_vals*sizeof(uint64_t));
    uint64_t x0=lower_bound,
        x1=upper_bound,y=0;
    for(uint64_t i=0;i<nb_vals;i++){
        y=(1+arc4random_uniform(upper_bound-1));
        arr[i]=(uint64_t)pow(((pow(x1,p+1)-pow(x0,p+1))*y+pow(x0,p+1)),1./(p+1));
    }
    return arr;
}

/*
algorithm poisson random number (Knuth):
    init:
        Let L ← e−λ, k ← 0 and p ← 1.
    do:
        k ← k + 1.
        Generate uniform random number u in [0,1] and let p ← p × u.
    while p > L.
    return k − 1.
*/

//from wikipedia https://en.wikipedia.org/wiki/Poisson_distribution#Generating_Poisson-distributed_random_variables
uint64_t *poisson_dist_ints_v1(uint64_t nb_vals,double lambda){
    //Knuth's method
    double p,l,u;
    uint64_t *res=malloc(sizeof(uint64_t)*nb_vals);
    uint64_t i,k;

    for(i=0;i<nb_vals;i++){
        l=pow(EXP,-lambda);
        k=0;
        p=1.;
        do{
            k++;
            u=((double)arc4random() / UINT32_MAX);
            p=p*u;
        }while(p>l);
        res[i]=k-1;
    }
    return res;
}

/*wikipedia
algorithm Poisson generator based upon the inversion by sequential search:[54]:505
    init:
        Let x ← 0, p ← e−λ, s ← p.
        Generate uniform random number u in [0,1].
    while u > s do:
        x ← x + 1.
        p ← p × λ / x.
        s ← s + p.
    return x.
*/

//also from https://en.wikipedia.org/wiki/Poisson_distribution#Generating_Poisson-distributed_random_variables
uint64_t *poisson_dist_ints_v2(uint64_t nb_vals,double lambda){
    double p,s,u;
    uint64_t *res=malloc(sizeof(uint64_t)*nb_vals);
    uint64_t i,x;

    for(i=0;i<nb_vals;i++){
        x=0;
        p=pow(EXP,-lambda);
        s=p;
        u=((double)arc4random() / UINT32_MAX);
        while(u>s){
            x++;
            p=p*lambda/x;
            s+=p;
        }
        res[i]=x;
    }
    return res;  
}

Мои вопросы: что вы думаете об этих функциях в первую очередь? и где я могу найти аналогичные алгоритмы, кроме как для генерации целых чисел после нормального распределения и степенного распределения (кроме того, которое я уже использовал)? Спасибо.
PS: я не хочу использовать предопределенную библиотеку или что-то в этом роде, я ищу несколько простых алгоритмов, которые работают, я также не собираюсь читать книгу на +2000 страниц для этого, Эти функции будут использоваться только для тестирования другой программы, я не хочу тратить на них слишком много времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...