Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.77/196: Рейтинг темы: голосов - 196, средняя оценка - 4.77
1 / 1 / 0
Регистрация: 02.04.2013
Сообщений: 40
1

Генератор нормально распределенной случайной величины в заданном диапазоне

14.05.2013, 23:05. Показов 40139. Ответов 23
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте, некоторое время назад я создавал тему с вопросом о том как сгенерировать случайные числа в диапазоне от Ν до M, Z число раз. Тогда мне посоветовали следующий код

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
double dblRand(double min, double max) {
 
    double x=(double)rand()/RAND_MAX;
    return min+x*(max-min);
 
}
 
// ---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender) {
 
    ListBox1->Clear();
    randomize();
 
    int lim = 100000; // число можно и поскромнее поставить, либо использовать для 
                      // вывода массива нечто другое :)
 
    while (lim--)
        ListBox1->Items->Add(FloatToStr(dblRand(140, 160)));
 
}
Но в последствии я понял, что генерируется не нормально распределенная величина (также называемое распределением Гаусса), а равномерно распределенная величина (а может я ошибаюсь???). Подскажите генератор случайной величины которая распределена нормально (по Гауссу), и так чтобы генерировались случайные числа в диапазоне от Ν до M, Z число раз.

Добавлено через 23 часа 55 минут
Подскажите пожалуйста, срочно нужно.. совсем застопорился.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
14.05.2013, 23:05
Ответы с готовыми решениями:

Смоделировать алгоритм непрерывной случайной величины распределенной с плотностью
Прошу помощи, так как не могу выполнить данное задание. Делал на матлабе, но преподавателю это не...

Вероятность попадания нормально распределённой случайной величины
Случайная величина Х~N(10,2). Найти вероятность того, что в испытаниях Х примет значения больше 8 и...

Заданы математическое ожидание а и с.к.о. σ нормально распределенной случайной величины Х
Заданы математическое ожидание а и среднее квадратическое отклонение σ нормально...

Вычислить вероятность попадания нормально распределённой случайной величины в интервал
Помогите пожалуйста решить задачу оч нужно. Св х распределена нормально с математическим ожиданием...

23
670 / 198 / 29
Регистрация: 10.05.2012
Сообщений: 595
15.05.2013, 15:11 2
NikWhite,
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
 
using namespace std;
 
double gen(double mn, double mx) { // не используйте min max это функции из cmath
    int dx = mx - mn;
    double accur = 1e3;
    int fmx = dx * accur;
    double t = rand()%fmx;
    t /= accur;
    return mn + t;
}
 
int main() {
    for (int i = 0; i < 1000; i++) {
        printf("%.5lf\n", gen(39, 42));
    }
    return 0;
}
Добавлено через 1 минуту
NikWhite, ваще тут при больших значениях фигня будет

Добавлено через 1 минуту
NikWhite, если числа маленькие, то юзайте

Добавлено через 41 секунду
NikWhite, randMAX просто слишком маленький
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
15.05.2013, 15:18 3
NikWhite, для генерации нормально распределенных случайных величин используется преобразование Бокса-Мюллера. Гуглится легко, на все про все - три простенькие формулы.
1
127 / 131 / 11
Регистрация: 25.12.2011
Сообщений: 443
15.05.2013, 18:19 4
Цитата Сообщение от NikWhite Посмотреть сообщение
нормально распределенной случайной величины в заданном диапазоне
А что это за такое "нормальное распределение" на конечном отрезке?
0
1 / 1 / 0
Регистрация: 02.04.2013
Сообщений: 40
15.05.2013, 19:47  [ТС] 5
Цитата Сообщение от kamre Посмотреть сообщение
А что это за такое "нормальное распределение" на конечном отрезке?
Имеется, промежуток, например от 200 до 300, в этом промежутке нужно сгенерировать нормально распределенную случайную величину.
0
127 / 131 / 11
Регистрация: 25.12.2011
Сообщений: 443
15.05.2013, 20:41 6
Цитата Сообщение от NikWhite Посмотреть сообщение
в этом промежутке нужно сгенерировать нормально распределенную случайную величину
Почитайте про определение нормального распределения, там никаких промежутков нет, любое действительное значение может приниматься.
0
1 / 1 / 0
Регистрация: 02.04.2013
Сообщений: 40
15.05.2013, 23:41  [ТС] 7
Цитата Сообщение от 0x10 Посмотреть сообщение
NikWhite, для генерации нормально распределенных случайных величин используется преобразование Бокса-Мюллера. Гуглится легко, на все про все - три простенькие формулы.
Пробовал бокса-мюллера,но он жутко медленный (зависал даже на 10 значениях), совсем не подходит. решил использовать центральную предельную теорему

double NormalDistribution()
C++
1
2
3
4
5
6
7
{
    double S = 0.;    
    for (int i = 0; i < 12; ++i) 
        S += (double)rand() / RAND_MAX;
 
   return S - 6.;
}
Попытался сделать, чтобы это работало в конкретном диапазоне (от 200 до 300), но не получилось, попадаются числа выпадающие из этого диапазона.

Добавлено через 13 минут
Цитата Сообщение от kamre Посмотреть сообщение
Почитайте про определение нормального распределения, там никаких промежутков нет, любое действительное значение может приниматься.
Я могу генерировать случайною величину в заданном диапазоне, она получится равномерно распределенной на этом промежутке, а потом с помощью центральной предельной теоремы перейду к нормально распределенной.

И еще Χ принадлежит [-∞;+∞], теоретически есть промежутки.

Добавлено через 2 часа 30 минут
Цитата Сообщение от Ternsip Посмотреть сообщение
NikWhite,
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
 
using namespace std;
 
double gen(double mn, double mx) { // не используйте min max это функции из cmath
    int dx = mx - mn;
    double accur = 1e3;
    int fmx = dx * accur;
    double t = rand()%fmx;
    t /= accur;
    return mn + t;
}
 
int main() {
    for (int i = 0; i < 1000; i++) {
        printf("%.5lf\n", gen(39, 42));
    }
    return 0;
}
Добавлено через 1 минуту
NikWhite, ваще тут при больших значениях фигня будет

Добавлено через 1 минуту
NikWhite, если числа маленькие, то юзайте

Добавлено через 41 секунду
NikWhite, randMAX просто слишком маленький
Тут не нормально распределенная получается и мне нужно генерировать от 1000 значений.
0
Master of Orion
Эксперт .NET
6100 / 4956 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
15.05.2013, 23:44 8
Копипастю из старой своей методы:
Генерация нормально распределенных чисел. Неинтегрируемость функции нормального распределения не позволяет использовать приведенный метод. Поэтому для генерации нормально распределенных чисел применяется способ, основанный на центральной предельной теореме (ЦПТ). Согласно ЦПТ, распределение суммы независимых одинаково распределенных случайных величин с увеличением числа слагаемых стремится к нормальному распределению. Если слагаемые равномерно распределены в интервале [0,1], то
Генератор нормально распределенной случайной величины в заданном диапазоне

Сумма равномерных случайных величин сходится к нормальному распределению достаточно быстро, и практика показала, что уже при n > 10 сходимость хорошая.
Однако непосредственно пользоваться приведенными соотношениями нельзя из-за зависимости параметров распределения Y от числа слагаемых и жесткой связи между my и σ2y. Поэтому для нормальных случайных величин с заданными параметрами my и σy используется следующая двухэтапная процедура, основанная на устойчивости нормального распределения к линейному преобразованию.
В начале формируется последовательность чисел {z}, подчиненных нормированному нормальному распределению (т.е.нормальному распределению с параметрами mz = 0; σz=1). Для этого выполняется операция
Название: 2.JPG
Просмотров: 4180

Размер: 9.7 Кб
Как нетрудно видеть, mz = 0; σz=1.
Затем последовательность {z} преобразуется в требуемую последовательность
{y} по формуле
Название: 3.JPG
Просмотров: 4175

Размер: 9.4 Кб
Следует обратить внимание, что для получения одного числа последовательности {y} надо использовать 12 равномерных чисел.
Программа, реализующая описанную процедуру, в отличие от датчика равномерных чисел, может не содержаться в математическом обеспечении компьютера.
0
1 / 1 / 0
Регистрация: 02.04.2013
Сообщений: 40
16.05.2013, 19:31  [ТС] 9
Цитата Сообщение от Psilon Посмотреть сообщение
Копипастю из старой своей методы:
Ну код, наверное, так и выглядит
C++
1
2
3
4
5
6
7
{
    double S = 0.;    
    for (int i = 0; i < 12; ++i) 
        S += (double)rand() / RAND_MAX;
 
   return S - 6.;
}
0
Master of Orion
Эксперт .NET
6100 / 4956 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
16.05.2013, 19:54 10
Ну а чего вам еще не хватает??
0
1 / 1 / 0
Регистрация: 02.04.2013
Сообщений: 40
16.05.2013, 22:49  [ТС] 11
Цитата Сообщение от Psilon Посмотреть сообщение
Ну а чего вам еще не хватает??
Дело то как раз и в промежутке, когда я генерирую равномерно распределенную случайную величину в промежутке от 200 и до 300, то все ок, но потом же эти значения используются в коде который я прислал, они складываются и в итоге распределение нормальное,а значения в этом промежутке не находятся (там получаются значения от 2х тысяч). Надо как то переписать код, чтобы значения были и нормально распределенные и находились в промежутке от 200 до 300.
0
Master of Orion
Эксперт .NET
6100 / 4956 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
16.05.2013, 23:07 12
Еще раз:
https://www.cyberforum.ru/cgi-bin/latex.cgi?y =  {\sigma}_{y}z + {m}_{y}
1
1 / 1 / 0
Регистрация: 02.04.2013
Сообщений: 40
19.05.2013, 18:46  [ТС] 13
Цитата Сообщение от Psilon Посмотреть сообщение
Еще раз:
https://www.cyberforum.ru/cgi-bin/latex.cgi?y =  {\sigma}_{y}z + {m}_{y}
Так не работает.Видимо не совсем поняли. Мне нужно сделать так чтобы нормально распределенная случайная величина находилась в промежутке от 200 до 300, но так сделать нельзя, поэто нужно нгенерировать равномерную от 200 до 300, перевести ее в нормальную, и сделать проекцию, как буд то, нормально распределенная находится от 200 и до 300.
0
Master of Orion
Эксперт .NET
6100 / 4956 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
19.05.2013, 19:04 14
NikWhite, омг, в вашем случае mx = 250, https://www.cyberforum.ru/cgi-bin/latex.cgi?\sigmax = 100/6 ~ 16.67
1
1 / 1 / 0
Регистрация: 02.04.2013
Сообщений: 40
19.05.2013, 23:42  [ТС] 15
Цитата Сообщение от Psilon Посмотреть сообщение
NikWhite, омг, в вашем случае mx = 250, https://www.cyberforum.ru/cgi-bin/latex.cgi?\sigmax = 100/6 ~ 16.67
250 получилась в результате (300+250)/2, а сигма -(300-200)/6 ? что за формула?что такое 6. Можете сказать в более общем виде, а то у меня границы любыми могут быть, не только 200 и 300.
0
Master of Orion
Эксперт .NET
6100 / 4956 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
19.05.2013, 23:45 16
NikWhite, в общем виде
https://www.cyberforum.ru/cgi-bin/latex.cgi?{m}_{x} = \frac{a + b}{2}, https://www.cyberforum.ru/cgi-bin/latex.cgi?{\sigma }_{x} = \frac{b - a}{6}
6 - теорема чебышева и правило 3 сигм
1
1 / 1 / 0
Регистрация: 02.04.2013
Сообщений: 40
20.05.2013, 00:05  [ТС] 17
Цитата Сообщение от Psilon Посмотреть сообщение
NikWhite, в общем виде
https://www.cyberforum.ru/cgi-bin/latex.cgi?{m}_{x} = \frac{a + b}{2}, https://www.cyberforum.ru/cgi-bin/latex.cgi?{\sigma }_{x} = \frac{b - a}{6}
6 - теорема чебышева и правило 3 сигм
Спасибо большое, а у вас есть ссылка на теорию, где расписано более подробно как все это работает.
0
Master of Orion
Эксперт .NET
6100 / 4956 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
20.05.2013, 00:12 18
NikWhite,
Генератор нормально распределенной случайной величины в заданном диапазоне
2
Форумчанин
Эксперт CЭксперт С++
8216 / 5046 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
20.05.2013, 02:52 19
А если без извращений, то в бусте и С++11 есть удобные инструменты для генерации чисел в указанном диапазоне.
Распределение normal_distribution<double> name(нижняя граница, верхняя граница) совместно c Вихрем Мерсенна (mt19937) творят чудеса без всяких извратов
1
2 / 2 / 0
Регистрация: 11.11.2013
Сообщений: 4
11.11.2013, 09:40 20
Цитата Сообщение от NikWhite Посмотреть сообщение
Подскажите генератор случайной величины которая распределена нормально (по Гауссу), и так чтобы генерировались случайные числа в диапазоне от Ν до M, Z число раз.
Не знаю снят ли до конца вопрос, но может кому пригодится. Так же прошу прощения за "много букв" но может кому будет интересно.

Тут нужно понимать что у нормального распределения есть такая характеристика как СКО(СреднеКвадратичное Отклонение) попробую объяснить на примере, что оно означает:
Например у нас есть выборка из 1000 значений (нормально распределенная) и например СКО (или сигма) = 30 означает, что 67% всех значений меньше либо равны 30.
Так же есть правило 2х сигм, говорящее о том что в диапазоне 2х сигм лежит 95% значений, и правило 3х сигм, говорящее о том, что 99,7% значений лежит в диапазоне 3х сигм.
Теперь на нашем примере:
67% (СКО, сигма) значений лежат в диапазоне от [-30, 30]
95% (2 сигма) значений лежат в диапазоне от [-60, 60] (30*2 = 60)
99,7% (3 сигма) значений лежат в диапазоне от [-90, 90] (30*3 = 90)

Теперь вернемся к твоей задаче, тебе нужны числа от M до N, не очень удачное обозначение, т.к. М обычно обозначается математическое ожидание(среднее значение), поэтому перефомулируем, так: нужны числа в диапазоне от N1 до N2, получаем:
M (мат. ожидание) = (N2+N1) / 2 (это просто среднее значение, от которого может колебатся ошибка)
3 сигма = M-N1, т.е. M-N1 это максимальное значение которое может принимать ошибка, и говоря о 3 сигма, мы говорим, что мы хотим такую выборку, 99,7% которой не больше M-N1
соответственно СКО (сигма) = 3 сигма / 3 = (M-N1)/3 это то значение с которым ты должен использовать генератор нормальных чисел, чтобы генерируемые значения не выходили из твоего диапазона.

Далее сам генератор:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
float gaussrand(float MO, float sko)
{
    float sum=0, x;
 
    for (int i=0;i<28;i++)
        sum+=1.0*rand()/RAND_MAX;
    x = (sqrt(2.0)*(sko)*(sum-14.))/2.11233 + MO;
 
    return x;
}
Цифра «28» и «2.11233» получены эмпирическим путем (читай методом научного тыка), значения были подобраны таким образом, что бы сигме соответствовало 67% значений, 2ум сигмам 95% значений, ну и 3м сигмам 99,7% значений (другие подобные функции редко проходят подобную проверку). Так же было проверено следующее: если сгенерировать 2е случайные, нормально распределенные величины и их сложить, то СКО этой величины должно быть равно qsrt(2)*сигма, моя функция проходит эту проверку.

Результат работы генератора:
Генерировалось 10.000.000 значений с СКО = 0.3, потом вычислялась статистика полученной выборки, результат:
67% = 0.299913049 | 95% = 0.600402057 | 99.7% = 0.900952756
67% = 0.300060332 | 95% = 0.600611031 | 99.7% = 0.901350796
67% = 0.299943686 | 95% = 0.600414336 | 99.7% = 0.900437713
67% = 0.300084651 | 95% = 0.60008353 | 99.7% = 0.901191831
67% = 0.299931049 | 95% = 0.599887371 | 99.7% = 0.90083015
67% = 0.299906909 | 95% = 0.600438833 | 99.7% = 0.901222467
67% = 0.300041765 | 95% = 0.600383639 | 99.7% = 0.900027037
67% = 0.300010741 | 95% = 0.60065949 | 99.7% = 0.900523663
67% = 0.299839497 | 95% = 0.600499749 | 99.7% = 0.900946617
67% = 0.300182939 | 95% = 0.600420237 | 99.7% = 0.901810706
Среднее СКО = 0.299977

Ошибка генератора 0.0077% ничтожно малое значение.

Ну и пример использования:
Например, функция для решения твоей задачи будет иметь следующий вид (сохраняя твои обозначения):

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//Числа генерируются в диапазоне [N, M]
//Генерируется Z чисел
//Сгенерированные значения будут помещены в массив array
void gen_array( const double N, const double M, const int Z, double *array )
{
  double average = ( N + M ) / 2.;
  double sigma = ( average – N ) / 3.;
 
  for( int i=0; i<Z; i++ ) {
    double new_value = gaussrand( average, sigma );
 
    //есть вероятность (0.3%) что сгенерированное число выйдет за нужный нам диапазон
    while( new_value < N || new_value > M )
      new_value = gaussrand( average, sigma ); //если это произошло генерируем новое число.
 
    array[i] = new_value;
  }
}
Пример вызова:
C++ (Qt)
1
2
3
4
5
6
void main()
{
  double array[1000];
  gen_array( 50, 100, 1000, array );
  //будет сгенерировано 1000 значений в диапазоне [50, 100]
}
С уважением Алексей

Добавлено через 1 час 26 минут
Цитата Сообщение от JleLLlka Посмотреть сообщение
Цифра «28» и «2.11233» получены эмпирическим путем (читай методом научного тыка)
Не дают чето свое же сообщение поправить, сейчас ещё по эмпирировал
Лучше использовать числа 25 и 1.99661, т.е. функция примит вид:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
float MainWindow::gaussrand(float MO, float sko)
{
    float sum=0, x;
 
    for (int i=0;i<25;i++)
        sum+=1.0*rand()/RAND_MAX;
    x = (sqrt(2.0)*(sko)*(sum-12.5))/1.99661 + MO;
 
    return x;
}
Результат:
67% = 0.300074607 | 95% = 0.600425005 | 99.7% = 0.899374366
67% = 0.299821496 | 95% = 0.600100815 | 99.7% = 0.898648262
67% = 0.300249696 | 95% = 0.600120068 | 99.7% = 0.898583174
67% = 0.299997002 | 95% = 0.600055397 | 99.7% = 0.898914099
67% = 0.300120205 | 95% = 0.600100577 | 99.7% = 0.900645971
67% = 0.299815416 | 95% = 0.599782825 | 99.7% = 0.900483012
67% = 0.299841166 | 95% = 0.600009799 | 99.7% = 0.898874998
67% = 0.300061643 | 95% = 0.599899948 | 99.7% = 0.899212003
67% = 0.300081104 | 95% = 0.600217521 | 99.7% = 0.900146246
67% = 0.300067931 | 95% = 0.600314617 | 99.7% = 0.899646521
среднее ско: 0.300013
2
11.11.2013, 09:40
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
11.11.2013, 09:40
Помогаю со студенческими работами здесь

Какой вид имеет функция плотности нормально распределённой случайной величины Х, если ее математическое ожидание M(X) =
Какой вид имеет функция плотности нормально распределённой случайной величины Х, если ее...

Найти дисперсию нормально распределенной величины
Определить дисперсию нормально распределенной случайной величины, если известно ее математическое...

Математическое ожидание симметрично распределенной случайной величины
Здравствуйте! Есть такая задача доказать что МО СВ X^3 равно нулю, при том что СВ X...

Распределение синуса равномерно распределенной случайной величины
Доброго времени суток. Помогите, пожалуйста, найти функцию распределения случайной величины,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Как работать с ветками (branch) в Git
InfoMaster 17.01.2025
Система контроля версий Git произвела революцию в процессе разработки программного обеспечения, предоставив разработчикам мощный инструмент для управления изменениями в коде. Одной из наиболее важных. . .
Как откатить последние коммиты в Git
InfoMaster 17.01.2025
Система контроля версий Git стала неотъемлемой частью современной разработки программного обеспечения, предоставляя разработчикам мощные инструменты для управления изменениями в коде. Одним из. . .
Что такое boilerplate и scaffold, чем они отличаются
InfoMaster 17.01.2025
В современном мире разработки программного обеспечения эффективность и скорость создания качественного кода играют crucial роль в успехе проектов. Разработчики постоянно ищут способы оптимизировать. . .
Чем отличаются ссылки и указатели в С++
InfoMaster 17.01.2025
В современном программировании на C++ эффективная работа с памятью является ключевым аспектом разработки качественного программного обеспечения. Указатели и ссылки представляют собой два. . .
В чем разница между PUT и POST
InfoMaster 17.01.2025
В современной веб-разработке правильное использование HTTP-методов играет ключевую роль в создании надежных и эффективных API-интерфейсов. Протокол HTTP прошел долгий путь развития с момента своего. . .
DTO, POCO и Value Object: что это такое, когда и как использовать
InfoMaster 17.01.2025
Введение в паттерны передачи данных В современной разработке программного обеспечения эффективное управление данными и их передача между различными слоями приложения являются ключевыми аспектами. . .
Что такое pull request в Git
InfoMaster 17.01.2025
В современной разработке программного обеспечения pull request в Git представляет собой ключевой механизм для эффективного взаимодействия между разработчиками при работе над общим кодом проекта. По. . .
Как вернуться к предыдущему коммиту в Git
InfoMaster 17.01.2025
Система контроля версий Git представляет собой мощный инструмент для управления изменениями в программном коде, который позволяет разработчикам эффективно отслеживать и контролировать историю. . .
Что такое паттерны программировани­я и проектирования
InfoMaster 17.01.2025
Роль паттернов в современной разработке программного обеспечения В современном мире разработки программного обеспечения паттерны проектирования стали неотъемлемой частью профессионального подхода. . .
Как добавить конструктор Яндекс Карт на сайт
InfoMaster 17.01.2025
Введение в API Яндекс Карт В современной веб-разработке интеграция картографических сервисов стала неотъемлемой частью многих проектов. API Яндекс Карт представляет собой мощный инструмент для. . .
Что такое javascript:void­­(0) и зачем это нужно
InfoMaster 17.01.2025
Когда вы сталкиваетесь с веб-разработкой, особенно с использованием JavaScript, одной из директив, которая часто встречается, является javascript:void(0). Это выражение вызывает интерес из-за своей. . .
Что такое оркестрация и хореография микросервисов
InfoMaster 17.01.2025
Введение в оркестрацию и хореографию микросервисов В современном мире разработки программного обеспечения микросервисная архитектура стала ключевым подходом к созданию масштабируемых и гибких. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru