Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
Другие темы раздела
C++ Найти сумму чисел,встречающихся в строке (visual c++) http://www.cyberforum.ru/cpp-beginners/thread864089.html
Добрый вечер, помогите решить задачку ,пожалуйста!) Условие:Дана строка до точки, группа символов в которой между пробелами считается словом,знаки препинания от слова пробелом не отделается. Задача:Найти сумму чисел,встречающихся в строке.
C++ Не большой код, нужно написать коментарии хотябы на главные строчки! string fixErrors(string encfile) { int doh = 0; int sindromeOneOriginal; int sindromeTwoOriginal; int sindromeThreeOriginal; int sindromeOne; int sindromeTwo; http://www.cyberforum.ru/cpp-beginners/thread864077.html
BigInteger C++
Что это? Есть уже готовый класс со всякими функциями? Или просто каждое число BigInteger - это массив из цифр, и нужно самому все делать с нуля?)
C++ Хэширование
Ребят, я вообще не понимаю хэширование(( помоги пожалуйста с задачкой, буду признателен. Составить программу для поиска по хэшам данных. Дан текст. Произвести хэширование по словам. В модуле поиска, предусмотреть реализацию обработки случая, при котором хэш-коды различных данных совпадают.
C++ Разреженные матрицы http://www.cyberforum.ru/cpp-beginners/thread864065.html
(С++) Есть такое задание: Даны две разреженные ленточные матрицы. Из одной матрицы вычесть другую и результат занести в разреженную матрицу CSR. Помогите пожалуйста!
C++ Создать класс Matrix, реализующий двухмерный динамический массив типа int Здравствуйте! Задание: Создать класс Matrix, реализующий двухмерный динамический массив типа int. Конструктор должен заполнять массив случайными значениями в диапазоне -50, +50. #ifndef _MATRIX_H_ #define _MATRIX_H_ #include<iostream> #include<Windows.h> #include<time.h> using namespace std; подробнее

Показать сообщение отдельно
JleLLlka
0 / 0 / 0
Регистрация: 11.11.2013
Сообщений: 3
11.11.2013, 09:40     Генератор нормально распределенной случайной величины в заданном диапазоне
Цитата Сообщение от 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
 
Текущее время: 04:42. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru