Нормализованное распределение случайных чисел от 0 до 1 [0, 1) в C - PullRequest
3 голосов
/ 19 января 2012

У меня проблемы с сохранением случайно сгенерированных значений, которые обычно распределяются между 0 и 1 (включая 0, исключая 1) Я считаю, что алгоритм в основном правильный, я просто озадачен здесь. Любое понимание было бы замечательно.

Это необходимые файлы:

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

Нормально распределенная функция генератора случайных чисел:

float rand_normal(float mean, float stddev) 
{
    static float n2 = 0.0;
    float x, y, r;
    static int n2_cached = 0;
    if (!n2_cached) 
    {
        do
        {
            x = 2.0*rand()/RAND_MAX - 1;
            y = 2.0*rand()/RAND_MAX - 1;
            r = x*x + y*y;
        } while (r==0.0 || r>1.0);
        float d = sqrt(-2.0*log(r)/r);
        float n1 = x*d;
        float result = n1*stddev + mean;
        n2 = y*d;
        n2_cached = 1;
        return result;
    }
    else
    {
        n2_cached = 0;
        return n2*stddev + mean;
    }
}

основная функция, используемая только для тестирования.

int main()
{
    srand(time(NULL));
    int i;
    float min = 0.5, max = 0.5, r, avg = 0;
    float x, w;
    int n = 10000000;
    for (i=0; i<n; i++)
    {
        r = rand_normal(0.5, 0.09);
        if (r < min)
            min = r;
        else if ( r>max)
            max = r;
        avg += r;
    }
    avg /= (float)n;
    printf("min = %f\nmax = %f\navg = %f\n", min, max, avg);
    return 0;
}    

Если кому-то интересно, эта функция необходима для симуляции «генетического наследования у растений».

Ответы [ 2 ]

2 голосов
/ 27 июня 2012

Почему вы ожидаете, что результат останется между 0 и 1? Гауссово распределение имеет полную поддержку, поэтому независимо от того, на какой интервал вы смотрите и какое бы значение и дисперсию вы ни выбрали, всегда будет (вероятность очень мала) ненулевая вероятность выпадения за пределы этого интервала. Если вы действительно хотите по какой-то причине ограничиться [0,1], то вы можете просто вызывать rand_normal, пока не попадете в этот интервал.

Обратите внимание, что хотя Box-Müller (используемый вами алгоритм) легко реализовать, это один из худших и наиболее дорогостоящих способов генерации гауссовской случайной величины. Лучший и самый быстрый алгоритм, который я знаю, это метод "Зиккурат", реализацию которого можно найти по адресу

http://www.seehuhn.de/pages/ziggurat

0 голосов
/ 19 января 2012

Я бы определенно создал функцию для преобразования rand () в нормализованное значение с плавающей запятой.Например:

double
nrand ()
{
  return rand()/(RAND_MAX - 1);
}

Также вот несколько ссылок, которые могут помочь:

...