· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.A&O —› ТеорВер и C++

Посл.отвђт Сообщенiе


Дата: Июн 14, 2004 00:22:31

Я теорвер много косил в универе, поэтому люди добрые, помогите кто чем сможет…

У нас есть rand(), равный 0 ~ RAND_MAX.
Для удобства возьмем

double Rnd(void)
{
return double(rand())/RAND_MAX;
}


Теперь у нас есть Rnd, равная 0 ~ 1.
А теперь следующее. У нас есть
double f(double x),
и она является плотностью (или распределением – решайте сами, как будет проще) некоторой случайной величины.
А теперь внимание вопрос: Как выразить эту случайную величину через Rnd и f ?

PS: Считаем, что Rnd имеет линейное распределение.


Дата: Июн 14, 2004 01:17:01

Не очень понял. Есть плотность вероятности, и нужно выдавать случайные значения в соответствии с этой плотностью ? (например: имеем распределение Гаусса: нужно получить набор псевдослучайных данных по этому распределению). Тогда можно разбить распределение F(x)плотности на отрезки по Xi, разбить интервал [0,1] на отрезки, пропорциональные F[Xi] и, кидая случайное число, получать соответственно значение Xi.

1514475324__


Дата: Июн 14, 2004 01:42:54

Ну вообщем-то ты правильно понял. Вот только аттач твой не читается :(
А вот я не очень понял про твой способ...


Дата: Июн 14, 2004 10:43:10

Для непрерывных случайных величин
Чтобы сгенерировать случайную величину по функции распределения Y~F(x), нужно найти обратную к функции распределения F^(-1). Если r-равномерно распределенная величина, то y=F^(-1)(r) - распределена по заданному закону F(x).
Например: экспоненциальное распредедение F(x)=1-exp(-a*x).
Обратная функция F^(-1)(x)=-1/a*ln(1-x).
Если r - равномерно распределенная величина, тогда Z=F^(-1)(r)=-1/a*ln(1-r) - экспоненциально распределенная величина. При вычислениях (1-r) можно заменить на r.


Дата: Июн 14, 2004 15:28:20

Ну вообщем-то ты правильно понял. Вот только аттач твой не читается :( 
А вот я не очень понял про твой способ...


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

Начало проги. Переменные и т.п.
{$N+}
var
  i,j,k,l,h:longint;
  f,g:text;
  fname,fresult:string;
  E,dE,Sigma,z,z1,N1,N2:real;
  mas:array[1..200] of longint;
  gauss:array[0..2000] of double; { Набор отрезков }
  label esc;


Расперделение Гаусса - это: F(N) = (1/2sqrt(pi)*Sig) * exp( - (N-Naver)^2 / 2*Sig^2 ), где Naver - среднее распределния, а Sig - ширина распределения (среднеквадратичное отклонение).
begin
  { Определяем ширину распределения }
  Sigma:=10.0*125/20.00;
  { z будет суммой длин отрезков Fi }
  z:=0;
  { Заполняем массив gauss значениями Fi: }
  { gauss[0] = F[N0]; }
  { gauss[1] = F[N0]+F[N1]; }
  { gauss[2] = F[N0]+F[N1]+F[N2]; }
  { ... }
  { где F - значение плотности распределения Гаусса }
  gauss[0]:=0;
  { Всего будет 2000+1 отрезков }
  for i:=1 to 2000 do
    begin
      { Текущее значение аргумента распределения - Ni }
      N1:=i*0.2;
      { Вычисляем значение плотности вероятности F(Ni) }
      z1:=0.2*(1/(sigma*sqrt(2*3.14)))*exp(-(N1-200)*(N1-200)/(2*Sigma*Sigma ));
      z:=z+z1;
      gauss[i]:=z1+gauss[i-1];
    end;
  { Выводим полученное значение суммы длин отрезков }
  writeln(z);readln;
  { Получаю исходное состояние моделируемого распределения }
  for i:=1 to 200 do mas[i]:=0;
  { Разогрев генератора случайных чисел }
  randomize;
  { Тут я открываю какие-то файлы - наверное, с экспериментальными данными }
  fname:='c:\tp\bin\mgu\15.dat';
  fresult:='c:\tp\bin\mgu\all.dat';
  assign(f,fname);
  reset(f);
  k:=0;
  h:=1000;
  for i:=1 to 10000 do
    begin
      if i=h then writeln(i);
      if i=h then h:=h+1000;
      { Получение случаного значения по распределению  Гаусса }
      { Получаем случайное число } 
      l:=random(60000);
      j:=0;
      repeat
        j:=j+1;
        { Ищем номер отрезка - j - на котором выпало }
        { случайное число }
        if ((l/60000)>=Gauss[j-1]/z) and ((l/60000)<Gauss [j]/z) then dE:=(j*0.2-200);
      until (((l/60000)>=Gauss[j-1]/z) and ((l/60000)<Gauss[j]/z));
      j:=0;
      E:=125.0;
      E:=E+dE;
      if E<0 then goto esc;
      repeat
        j:=j+1;
        if (E>=((j-1)*125/20.00)) and (E<(j*125/20.00)) then mas[j]:=mas[j]+1;
        if (E>=((j-1)*125/20.00)) and (E<(j*125/20.00))   then k:=k+1;
       until  (E>=((j-1)*125/20.00)) and (E<(j*125/20.00));
esc:
  end;

  close(f);
  assign(f,fresult);
  rewrite(f);
  for i:=1 to 200 do
    begin
      writeln(f,i-1,' ',2500*mas[i]/k:4:0);
    end;
  close(f);
end.


Вот так примерно. Честно говоря, это черновик какой-то и было это в институте. Если будут вопросы, я попробую объяснить подробнее.


Дата: Июн 14, 2004 16:10:42

Вот. Подумал я и переписал понятнее:
{$N+}
const
  Sigma: double = 2.0;
  Aver:  double = 5.0;
  StepsNumber = 100; { Число разбиений оси X }
var
  Fi: double;   { Значение плотности распределения }
  Ni: double;   { Значение аргумента плотности распределения }
  Fsum: double; { Сумма значений всех отрезков - должна быть примерно 1, }
                { поскольку распределение нормировано на 1 }
  i,j: integer; { Рабочий индекс }
  gauss: array[0..StepsNumber] of double;
  RandVal: double; { Случайное число типа double }
begin
  { Инициализация генератора случайных чисел }
  randomize;
  Fsum:=0.0;
  gauss[0]:=0.0;
  for i:=0 to StepsNumber do
    begin
      { Вычисляем аргумент распределения - N }
      Ni:=((Aver*2)/StepsNumber)*i;
      Fi:=(1/(Sigma*sqrt(2*3.14)))*exp(-(Ni-Aver)*(Ni-Aver)/(2*Sigma*Sigma)) ;
      gauss[i]:=((Aver*2)/StepsNumber)*Fi+gauss[i-1];
      Fsum:=Fsum+((Aver*2)/StepsNumber)*Fi;
    end;
   { выводим сумму отрезков }
   writeln('Summ of Fi=',Fsum); readln;

   { Получаем "случайные" числа по распределению Гаусса }
   for j:=0 to 10 do
     begin
       RandVal:=random(10000)/10000;
       i:=-1;
       repeat
         inc(i);
         Ni:=((Aver*2)/StepsNumber)*i;
       until RandVal < gauss[i+1];
       writeln('rand val by gauss distr = ',Ni);
     end;
end.


Разумееется, таблицу плотностей готовить не обязательно - можно вычислять обратное значение. Но такой метод подходит для ПРОИЗВОЛЬНОГО распределения.


Дата: Июн 17, 2004 22:20:14

Kozyr
Минуточку... А в каких пределах заключена r? Ведь бесконечных распределений не бывает. Как выразить эту случайную величину через r=[0;1] ?


Дата: Июн 17, 2004 22:23:19

_Chingachguk_
Может я что-то не так понял, но похоже что ты выполняешь численное интегрирование плотности... Попахивает извращением...


Дата: Июн 18, 2004 10:19:19 · Поправил: Kozyr

_DEN_
Минуточку... А в каких пределах заключена r?
r - равномерно распределенная величина из [0;1].

Функция распределения F(x) - принимает значения из [0;1], x~R.
F^(-1)(x) принимает значения из R, а х должно быть из [0;1].

Данный метод как и вся математика: очень точный и иногда очень трудно реализуемый ;) Трудности связаны с нахождением обратной функции.
На enlight.ru есть примеры генераторов.


Дата: Июн 18, 2004 12:29:31

Kozyr
Все, прочувствовал :)
Спасибо за идею. По ссылочке обязательно слазию.


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.047