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

Рассчет определенного интеграла методом Монте-Карло. - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 43, средняя оценка - 4.88
Simply me
 Аватар для Simply me
235 / 31 / 2
Регистрация: 05.05.2012
Сообщений: 292
26.01.2013, 08:39     Рассчет определенного интеграла методом Монте-Карло. #1
Не могли бы вы посмотреть, я неправильно понимаю метод Монте Карло для нахождения определенного интеграла или неправильно его реализую?
Вот так я понимаю алгоритм:
Выбираем случайным образом N точек с абсциссами от a до b и ординатами от минимального значения функции до максимального на [a, b]. Проверяем для каждой точки, попадает ли она в область, ограниченную a, b, минимумом функции и максимумом функции. Считаем, сколько точек попало в область. Допустим, m. Тогда
(m/n)=(значение интеграла/s), где s, как я понимаю, - (b-a)*(макс. значение - мин. значение). Отсюда находим значение интеграла.
А вот код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#pragma hdrstop
#include <math.h>
#include <conio.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
//---------------------------------------------------------------------------
 
#pragma argsused
double func(double x, int n)
{
return pow(x,n);                             //степенная функция
}
int main(int argc, char* argv[])
{
        int a,b,n,d,i, st;
        double c;
        printf("st: ");                       //степень подинтегральной функции
        scanf("%d",&st);
        printf("\na: ");                    //нижний предел
        scanf("%d",&a);
        printf("\nb: ");                    //верхний предел
        scanf("%d",&b);
        printf("\nn: ");                    //число точек
        scanf("%d",&n);
        if (func(a,st)>=func(b,st))
        c=func(a,st);                    //максимальное значение функции
        else
        c=func(b,st);
        double *x=new double[n];
        double *y=new double[n];
        srand(time(NULL));
        d=int(c);
        int count=0;
        for  (i=0; i<n; i++)
        {
        x[i]=a+rand()%(b-a);                //случайные точки
        y[i]=rand()%d;
        if (y[i]<func(x[i],st))                
        count++;
        }
        double integral=count*(b-a)*c/n;
        printf("\nIntegral=%f", integral);
        getch();
        return 0;
}
Буду очень признательна, если найдете ошибку!
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Зосима
 Аватар для Зосима
4786 / 3155 / 293
Регистрация: 02.04.2012
Сообщений: 6,047
Записей в блоге: 13
Завершенные тесты: 1
26.01.2013, 14:50     Рассчет определенного интеграла методом Монте-Карло. #2
Simply me, лапка, теорию ты понимаешь верно! Интеграл это по сути площадь, ограниченная кривой.
В методе Монте-Карло мы, как ты верно заметила, выделяем прямоугольную область по х от a до b, а по y от min(y), до max(y), как ты верно заметила, площадь этого прямоугольника равна:
S = (b-a)*(max(y)-min(y))
Затем мы "загаживаем" эту область случайгыми числами с равномерным законом распределения и считаем общее число точек N и сколько из них оказалось ниже кривой M, тогда отношение количеств будет примерно равно отношению плошадей области Sk и под кривой:
M/N = Sk/S;
Причем чем больше точек тем более равным будет соотношение
Вспоминая, что площадь под кривой это есть интеграл, получаем:
Int_ab = Sk = S*M/N;
Чуток подправил программу:
c - это макс. функции, d - это мин. функции, соответственно подправил вычисления случ. величин.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#pragma hdrstop
#include <math.h>
#include <conio.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
//---------------------------------------------------------------------------
 
#pragma argsused
double func(double x, int n)
{
return pow(x,n);                             //степенная функция
}
int main(int argc, char* argv[])
{
        int n,i, st;
        double a, b, c, d;
        printf("st: ");                       //степень подинтегральной функции
        scanf("%d",&st);
        printf("\na: ");                    //нижний предел
        scanf("%d",&a);
        printf("\nb: ");                    //верхний предел
        scanf("%d",&b);
        printf("\nn: ");                    //число точек
        scanf("%d",&n);
        if (func(a,st)>=func(b,st))
        c=func(a,st);                    //максимальное значение функции
        d=func(b,st); //мин. значение ф-ции 
        else
        c=func(b,st);
 //max
        d=fucc(a,st); //min
        double *x=new double[n];
        double *y=new double[n];
        srand(time(NULL));
        int count=0;
        for  (i=0; i<n; i++)
        {
        x[i]=a+(b-a)*rand();                //случайные точки
 X
        y[i]=d+(c-d)*rand();
        if (y[i]<func(x[i],st))     
        count++;
        }
        double integral=count*(b-a)*(c-d)/n;
        printf("\nIntegral=%f", integral);
        getch();
        return 0;
}
Добавлено через 12 минут
Стоит заметить, что такое вычисление макс. и мин. как тут (c = func(a,st), например), справедливо только для монотонных функций!, а степенные ф-ции не все монотонны! Так например парабола (st=2) в точке x=-1 и в точке x=1 принимает одинаковое значение поэтому c = d и s = 0 и интеграл соответственно тоже!
Поэтому неплохо для начала найти макс. и мин. значения ф-ции на всем промежутке, т.е. рассчитать ее с каким-то мелким шагом и найти макс и мин значения массива:
C++
1
2
3
4
5
6
7
8
9
double x
c = func(a,st); //max
d = func(a, st); // min
for (x=a; x<=b; x+=(b-a)/500.0)
{
if (func(x,st)>c)  c=func(x,st);
if (func(x,st)<d)  d=func(x,st);
}
// и т.д.
(поправь меня, если ошибся, я не наСильник )

Добавлено через 3 минуты
PS: В этом разделе мы играемся с Матлабом

Добавлено через 1 час 42 минуты
Ах да! Забыл уточнить лапка, тебе программа нужна в MATLAB или на C++ ? Если на плюсах, то я перенесу сообщения в соответствующий раздел
Simply me
 Аватар для Simply me
235 / 31 / 2
Регистрация: 05.05.2012
Сообщений: 292
26.01.2013, 15:23  [ТС]     Рассчет определенного интеграла методом Монте-Карло. #3
Зосима, спасибо, все поняла))
Программа на с++. Я заметила, что тема создана в разделе про Matlab, просто думала, что сам метод не так поняла)
Зосима
 Аватар для Зосима
4786 / 3155 / 293
Регистрация: 02.04.2012
Сообщений: 6,047
Записей в блоге: 13
Завершенные тесты: 1
26.01.2013, 16:55     Рассчет определенного интеграла методом Монте-Карло. #4
Молодчика!
Ясненько тогда сейчас перенесу, чтобы братцы-нальники тоже могли глянуть, авось кому сгодится!
2GARIN_zmei
0 / 0 / 0
Регистрация: 11.06.2014
Сообщений: 2
11.06.2014, 01:12     Рассчет определенного интеграла методом Монте-Карло. #5
Был бы признателен если бы автор этой темы скинул сюда то что у него получилось. А то у меня тема Диплома по этому а я в матане как ёжик в тумане
Зосима
11.06.2014, 14:51
  #6

Не по теме:

2GARIN_zmei, дык в том, то и прелесть метода монте-карло, что необязательно разбираться в матане достаточно сидя под пледом у камина и потягивая глинтвейн много раз кинуть кубики

2GARIN_zmei
0 / 0 / 0
Регистрация: 11.06.2014
Сообщений: 2
15.06.2014, 12:59     Рассчет определенного интеграла методом Монте-Карло. #7
А вы не могли бы мне помочь? Я в корень не понимаю какие входные данные нужно вносить для решения интеграла?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.06.2014, 18:11     Рассчет определенного интеграла методом Монте-Карло.
Еще ссылки по теме:

C++ Странный интеграл методом Монте-Карло
Таблица умножения методом Монте-Карло C++
C++ Вычисление интеграла методом Монте-Карло

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

Или воспользуйтесь поиском по форуму:
Зосима
 Аватар для Зосима
4786 / 3155 / 293
Регистрация: 02.04.2012
Сообщений: 6,047
Записей в блоге: 13
Завершенные тесты: 1
15.06.2014, 18:11     Рассчет определенного интеграла методом Монте-Карло. #8
2GARIN_zmei, ключевые входные данные это:
- подынтегральная функция (строки 10-13)
- пределы интегрирования (строки 20-23)
- количество точек (строки 24,25)

степень (строки 18,19) - это просто параметр данной подынтегральной функции.
Yandex
Объявления
15.06.2014, 18:11     Рассчет определенного интеграла методом Монте-Карло.
Ответ Создать тему
Опции темы

Текущее время: 16:31. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru