На главную >>>


Как генерировать случайные числа, распределенные по определенному (степенному) закону

Алгоритм реализован в виде программы на языке С, которую вы можете скачать в разделе программы.

Во всех современных средах программирования существуют функции, генерирующие случайные числа. Чаще всего это бывают случайные числа равномерно распределенные на отрезке [0:1]. Равномерное распределение означает, что сгенерированное случайное число может попасть в любую точку интервала [0:1] с равной вероятностью. (Фраза "в любую точку" не совсем точна, но не будем углубляться в тонкости.)

Однако, для нужд народного хозяйства одного равномерного (uniform, англ.) распределения недостаточно. Во многих задачах в науке встречаются такие случайные явления, вероятность которых зависит от их величины. Например, когда на землю падают космические лучи, энергия каждой частицы - величина случайная, однако частиц с маленькой энергией больше, чем частиц с большой энергией. Аналогично, если мы разбиваем окно, количество осколков - величина случайная, однако маленьких осколков гораздо больше, чем больших.

Пусть f(x) - плотность вероятности случайной величины. Это означает, что чтобы найти вероятность, что случайная величина принимает значение от x до x+dx нужно найти произведение f(x)dx.

Функцией распределения случайной величины называется величина F(x) равная вероятности того, что случайная величина, полученная в некотором событии, меньше x.

Функция распределения и плотность вероятности связаны между собой соотношениями

В данной статье описано как генерировать случайные числа с определенным распределением вероятности, на примере, когда плотность вероятности обратно пропорциональна некоторой степени величины

По определению, вероятность обнаружить случайную величину на всем интервале определения равна единице. Т.е. плотность вероятности должна быть пронормирована:

Тогда в случае степенной плотности вероятности
постоянная нормировки будет равна:

В таком случае функция распределения будет равна

Зная функцию распределения F(x) случайной величины, можно генерировать случайную величину с таким распределением используя генератор равномерно распределенных случайных чисел. Пусть у нас есть генератор, выдающий случайное число r равномерно распределенное на интервале [0:1]. Тогда F -1(r) будет распределено по нужному закону. Здесь F -1(r) означает функцию обратную к F(x).

Обратной функцией к F(x) будет

Значит, чтобы найти очередное случайное число, распределенное по нужному закону, зная r, нужно вычислить:

Ниже написан пример программы на С, в которой генерируются случайные числа с степенным распределением типа f(x)~x-2. Показатель степени указан в переменной alpha=-2 Сами случайные числа принимают значения от x0=1 до x1=10. Количество случайных чисел управляется переменной N = 300000. Все они пишутся в файл с именем outname = "r.txt". Случайное число, равномерно распределенное на интервале [0:1] обозначено буквой r, сама сгенерированная величина буквой E.

//
//generate random numbers with spectra like x^(-2)
//
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void main(){
    long N = 300000;        //number of generated randoms
    float r=0;              //uniform distributed random in [0:1]
    float alpha=-2;         //power of spectra
    float x0=1;             //x min of generated randoms
    float x1=10;            //x max of generated randoms

    float p0=0, p1=0;       //temporary var for powers
    float E=0;              //generated random
    char* outname = "r.txt";  //name of file of generated randoms

    FILE* OUT;

    OUT = fopen(outname, "wt");

    p0 = pow(x0, alpha + 1);
    p1 = pow(x1, alpha + 1);

    randomize();

    for(long i=0; i<N; i++){
	r = (float)rand()/RAND_MAX;
	if(r==0){                     //awoid to take log(0)
	    continue;
	}
	E = pow(r * (p1 - p0) + p0, 1.0/(alpha + 1.0));
	fprintf(OUT, "%f\n", E);
    }
    fclose(OUT);
}

Надеюсь, что вам стало все понятно.


На главную >>>