Метод кусочной аппроксимации плотности распределения вероятности
Автор: Shch • Сентябрь 14, 2025 • Лабораторная работа • 2,325 Слов (10 Страниц) • 1,727 Просмотры
ГУАП
КАФЕДРА № 21
ОТЧЕТ
ЗАЩИЩЕН С ОЦЕНКОЙ
ПРЕПОДАВАТЕЛЬ
Канд. техн. наук | Н.А. Гладкий | |||
должность, уч. степень, звание | подпись, дата | инициалы, фамилия |
ОТЧЕТ О ЛАБОРАТОРНОЙ РАБОТЕ №3 |
Метод кусочной аппроксимации плотности распределения вероятности (метод Брусленко Н.П.) |
по курсу: «Моделирование систем и процессов в радиоэлектронных системах» |
РАБОТУ ВЫПОЛНИЛ
СТУДЕНТ гр. № | 2310 | А.А. Щербань | |||
подпись, дата | инициалы, фамилия |
Санкт-Петербург 2025
- Цель
В соответствии с номером варианта необходимо сгенерировать выборку случайных чисел с заданным законом распределения с помощью метода Брусленко Н.П., исследовать данный метод.
- Выполнение работы
Заданный закон распределения[pic 1]
- Подставляем известные значения[pic 2][pic 3]
Рисунок 1 – График, построенный по формуле плотности распределения
- Алгоритм
Алгоритм работы программы поделен мной на 6 блоков:
- для подпрограмм:
А) создание функции с заданным законом распределения;
Б) создание функции численного интегрирования методом средних прямоугольников;
- для основной программы:
В) Численный поиск максимума функции;
Г) Поиск правой границы b (где функция < 1% от максимума);
Д) Подготовка данных для метода Брусленко;
Е) Генерация случайных чисел методом Брусленко[pic 4]
Рисунок 1 – Алгоритм программы блока А
а) б)[pic 5][pic 6]
Рисунок 2 (а,б) – Алгоритм работы программы: а) блока Б; б) блока В[pic 7]
Рисунок 3 – Алгоритм работы программы блока Г
а) б) [pic 8][pic 9]
Рисунок 4 (а,б) – Алгоритм работы программы: а) блока Д, б) блока Е
- Программа (C++)
- #include <iostream>
- #include <cmath>
- #include <ctime>
- #include <cstdlib>
- using namespace std;
- /*
- Функция плотности вероятности
- y - входное значение
- Возвращает значение функции плотности в точке y
- */
- double func(double y) {
- return pow(y, 3) * exp(-y * y / 2.0) / 2.0;
- }
- /*
- * Функция численного интегрирования методом средних прямоугольников
- * a - нижний предел интегрирования
- * b - верхний предел интегрирования
- * Возвращает значение интеграла от a до b с точностью E
- */
- double integ(double a, double b) {
- const double E = 0.001; // желаемая точность вычисления интеграла
- int n = 1; // начальное количество интервалов разбиения
- double h = (b - a) / n; // Шаг интегрирования
- double S1 = 0, S2; // S1 - текущая сумма, S2 - предыдущая сумма
- do {
- n *= 2; // Удваиваем количество интервалов
- h = (b - a) / n; // Пересчитываем шаг интегрирования
- S2 = S1; // Сохраняем предыдущее значение суммы
- S1 = 0; // Обнуляем текущую сумму
- // Суммируем значения функции в средних точках интервалов
- for (int i = 0; i < n; ++i) {
- S1 += func(a + (i + 0.5) * h);
- }
- S1 *= h; // Умножаем сумму на шаг интегрирования
- // Повторяем, пока не достигнем нужной точности
- } while (fabs(S1 - S2) > E);
- return S1;
- }
- int main() {
- // Инициализация генератора случайных чисел текущим временем
- srand(static_cast<unsigned>(time(nullptr)));
- // Численный поиск максимума функции
- double max_y = 0; // Максимальное значение функции
- double x = 0; // Точка, где достигается максимум
- double s = 0.001; // Шаг поиска
- double y0 = 0.1; // Начальная точка поиска (избегаем y=0)
- // Ищем максимум на интервале [0.1, 10.0]
- while (y0 <= 10.0) {
- double val = func(y0); // Значение функции в текущей точке
- // Если нашли большее значение, обновляем максимум
- if (val > max_y) {
- max_y = val;
- x = y0;
- }
- // Переходим к следующей точке
- y0 += s;
- }
- cout << "max y = " << max_y << endl;
- // Поиск правой границы b
- double d = 0.1; // Шаг поиска границы
- double y = x; // Начинаем поиск от точки максимума
- double b = x; // Правая граница области
- // Двигаемся вправо, пока значение функции > 1% от максимума
- while (func(y) > max_y * 0.01) {
- y += d;
- b = y;
- }
- cout << "b = " << b << endl;
- // Подготовка данных для метода Брусленко
- const int K = 100; // Количество интервалов разбиения
- double yk[K + 1]; // Массив границ интервалов
- double F[K + 1] = { 0 }; // Массив значений интегральной функции
- // Равномерное разбиение интервала [0, b] на K частей
- for (int k = 0; k <= K; ++k) {
- yk[k] = k * b / K; // Вычисляем k-ю границу
- }
- // Вычисление интегральной функции распределения
- for (int k = 1; k <= K; ++k) {
- F[k] = F[k - 1] + integ(yk[k - 1], yk[k]);
- }
- //Нормировка интегральной функции
- for (int k = 1; k <= K; ++k) {
- F[k] /= F[K]; // Делим все значения на F[K] (интеграл по всей области)
- }
- // Генерация случайных чисел
- for (int i = 0; i < 100; ++i) {
- //Генерируем равномерно распределенное число c1 ∈[0, 1]
- double c1 = static_cast<double>(rand()) / RAND_MAX;
- //Находим интервал k, где F[k] <= c1 < F[k + 1]
- int k = 0;
- while (k < K && F[k + 1] < c1) {
- k++;
- }
- //Генерируем второе равномерное число c2 ∈ [0,1]
- double c2 = static_cast<double>(rand()) / RAND_MAX;
- //Линейная интерполяция внутри выбранного интервала
- double n = yk[k] + (yk[k + 1] - yk[k]) * c2;
- cout << n << endl;
- }
- return 0;
- }
а) б)[pic 10][pic 11]
...