2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки


Правила форума


Посмотреть правила форума



Начать новую тему Ответить на тему
 
 Метод Монте-Карло - какие-то жуткие значения
Сообщение06.06.2016, 23:41 


28/02/15
52
Пытаюсь написать программу для интегрирования методом Монте-Карло.
По задаче:
$$\int\limits^1_0x^{-1/4}(1-x)^{-3/4}dx=\frac{\pi}{\sin({3\pi/4})}$$
Мало того, что WolframAlpha выдаёт, что точное значение в 2 раза больше, так ещё и в самих вычислениях какая-то хрень творится.
Пусть $\xi_i\in[0;1]$ - это у нас
Используется синтаксис C++
(double)(rand())/RAND_MAX;
,
а $\rho(x)=1$. Тогда $x_i=\xi_i+a$.
Написал такой код:
Используется синтаксис C++
for (int i=0; i<N; i++){
        x[i]=r()+a;
        //cout<<x[i]<<" "<<f(x[i])<<endl;
        sum+=f(x[i]);
    }
    //cout<<sum<<endl;
    I1=sum/N;
    for (int i=0; i<N; i++) sq+=pow(f(x[i])-I1,2);
    disp1=sqrt(sq/(N-1));
    cout<<"При rho=1:"<<endl<<"I^="<<I1<<", sigma^="<<disp1<<endl;

Результаты:
$N=10: \hat I=2,915; \hat\sigma=1,68875$
$N=100: \hat I=3,32821; \hat\sigma=3,17415...$
Понял, что фигня какая-то, попробовал сменить $\rho: \rho(x)=2(x+2)/3$.
Используется синтаксис C++
    for (int i=0; i<N; i++){
        x[i]=-2+sqrt(4+2*r()/C);
        cout<<x[i]<<" "<<f(x[i])/(C*(x[i]+2))<<endl;
        sum+=f(x[i])/(C*(x[i]+2));
    }
    I2=sum/N;
    for (int i=0; i<N; i++) sq+=pow(f(x[i])/(C*(x[i]+2))-I2,2);
    disp2=sqrt(sq/(N-1));
    cout<<"При rho=x+2:"<<endl<<"I^="<<I2<<", sigma^="<<disp2<<endl;

Лучше не стало:

$N=10: \hat I=3,60127; \hat\sigma=10,1102$
Почему у интеграла получаются такие значения и какая-то жуткая дисперсия? Что здесь не так?

 Профиль  
                  
 
 Re: Метод Монте-Карло - какие-то жуткие значения
Сообщение06.06.2016, 23:54 
Аватара пользователя


11/06/12
10390
стихия.вздох.мюсли
byulent в сообщении #1129593 писал(а):
Мало того, что WolframAlpha выдаёт, что точное значение в 2 раза больше
Всё она верно выдаёт.

 Профиль  
                  
 
 Re: Метод Монте-Карло - какие-то жуткие значения
Сообщение07.06.2016, 01:26 
Заслуженный участник
Аватара пользователя


23/07/08
10910
Crna Gora
Сходимость очень плохая из-за того, что область между графиком $f(x)=x^{-1/4}(1-x)^{-3/4}$ и осью абсцисс неограниченная (потому что сама функция неограничена). Даже при миллионе точек точность неприемлемая. Чтобы улучшить сходимость, можно взять такую функцию $f_0(x)$, чтобы интеграл $\int\limits_0^1 f_0(x)\;dx$ легко брался, а разность $f(x)-f_0(x)$ была уже ограниченной на $[0,1]$. Например,
$f_0(x)=x^{-1/4}+(1-x)^{-3/4}$
Ну, и искать методом Монте-Карло интеграл
$\int\limits_0^1 (f(x)-f_0(x))\;dx$,
прибавив затем найденный аналитически $\int\limits_0^1 f_0(x)\;dx$.
Я проверил, это помогает, хотя точек всё равно надо брать много.

 Профиль  
                  
 
 Re: Метод Монте-Карло - какие-то жуткие значения
Сообщение07.06.2016, 07:01 


28/02/15
52
Aritaborian в сообщении #1129597 писал(а):
Всё она верно выдаёт.


Да, извиняюсь, забыл, что $2/\sqrt{2}=\sqrt{2}$.

-- 07.06.2016, 07:21 --

В коде ошибок точно нет?
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
double f (double x){return pow(x,-0.25)*pow(1-x,-0.75);} //функция
double r (){return (double)(rand())/RAND_MAX;} //случайное число, равномерно распределённое на единичном отрезке

int main()
{
    /**
    * Метод Монте-Карло
    **/

    setlocale(LC_ALL,"rus");
    double I1, disp1, I2, disp2, I3, disp3, a, b, *x, sum=0, sq=0;
    int N;
    cout<<"Введите пределы интегрирования"<<endl;
    cin>>a>>b;
    cout<<"Введите количество испытаний"<<endl;
    cin>>N;
    x = new double[N];
    srand(time(0));
    //p=1
    for (int i=0; i<N; i++){
        x[i]=r()+a;
        //cout<<x[i]<<" "<<f(x[i])<<endl;
        sum+=f(x[i]);
    }
    //cout<<sum<<endl;
    I1=sum/N;
    for (int i=0; i<N; i++) sq+=pow(f(x[i])-I1,2);
    disp1=sqrt(sq/(N-1));
    cout<<"При rho=1:"<<endl<<"I^="<<I1<<", sigma^="<<disp1<<endl;
    //p=x+2
    sum=0;
    double C=1/(pow(b,2)/2+2*b-pow(a,2)/2-2*a);
    //cout<<C<<endl;
    for (int i=0; i<N; i++){
        x[i]=-2+sqrt(4+2*r()/C);
        //cout<<x[i]<<" "<<f(x[i])/(C*(x[i]+2))<<endl;
        sum+=f(x[i])/(C*(x[i]+2));
    }
    I2=sum/N;
    for (int i=0; i<N; i++) sq+=pow(f(x[i])/(C*(x[i]+2))-I2,2);
    disp2=sqrt(sq/(N-1));
    cout<<"При rho=x+2:"<<endl<<"I^="<<I2<<", sigma^="<<disp2<<endl;
    return 0;
}

 Профиль  
                  
 
 Re: Метод Монте-Карло - какие-то жуткие значения
Сообщение07.06.2016, 08:27 
Заслуженный участник
Аватара пользователя


18/05/06
13440
с Территории
Код проверьте на какой-нибудь нормальной функции, без бесконечностей. Лучше на нескольких.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 5 ] 

Модераторы: Модераторы Математики, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group