卡在使用蒙特卡罗积分法?

时间:2019-06-24 22:16:41

标签: c++ montecarlo

我想使用monte-carlo集成方法,下面是我的代码。如您所见,我确定了间隔积分,但是结果是错误的!此代码有什么问题?

任何帮助将不胜感激。

#include <iostream>
#include <math.h>
#include <stdlib.h>

#define N 500
using namespace std;

double Func(double x) { return pow(x, 2) + 1; }

double Monte_Carlo(double Func(double), double xmin, double xmax, double ymin,
                   double ymax)
{

    int acc = 0;
    int tot = 0;
    for (int count = 0; count < N; count++)
    {

        double x0 = (double)rand() / 4 + (-2);
        double y0 = (double)rand() / 4 + 0;

        float x = x0 / (float)RAND_MAX;
        float y = y0 / (float)RAND_MAX;
        cout << x << endl;


        if (y <= Func(x))
            acc++;

        tot++;

        // cout << "Dgage" << tot << '\t' << acc << endl;
    }

    double Coeff = acc / N;

    return (xmax - xmin) * (1.2 * Func(xmax)) * Coeff;
}

int main()
{

    cout << "Integral value is: " << Monte_Carlo(Func, -2, 2, 0, 4) << endl;

    system("pause");
    return 0;
}

1 个答案:

答案 0 :(得分:0)

Monte_Carlo函数使事情变得比他们需要的复杂。对于集成一维函数,我们要做的就是在要积分的区域内多次采样函数的值:

#include <random>

double Monte_Carlo(double Func(double), double xmin, double xmax, int N) 
{
    // This is the distribution we're using to generate inputs
    auto x_dist = std::uniform_real_distribution<>(xmin, xmax);

    // This is the random number generator itself
    auto rng = std::default_random_engine(); 

    // Calculate the total of N random samples
    double total = 0.0; 
    for(int i = 0; i < N; i++) {
        double x = x_dist(rng); // Generate a value

        total += Func(x); 
    }  

    // Return the size of the interval times the total, 
    // divided by the number of samples
    return (xmax - xmin) * total / N;
}

如果我们使用N = 1000运行此代码,我们将得到一个整数值9.20569,非常接近确切的答案(9.33333...)。

// It's much more efficent to use x*x instead of pow
double func(double x) { return x * x + 1; }

int main()
{

    cout << "Integral value is: " << Monte_Carlo(func, -2, 2, 1000) << endl;

    getchar(); // Pause until the user presses enter
    return 0;
}

我们还可以尝试N的多个值,以使程序显示其收敛方式。以下程序计算从20的{​​{1}}的幂为N的积分

30

输出显示monte carlo方法确实收敛:

#include <iostream>
#include <cmath>
#include <random>

using namespace std;

double func(double x) { return x*x + 1; }

double Monte_Carlo(double Func(double), double xmin, double xmax, int N) {

    auto x_dist = std::uniform_real_distribution<>(xmin, xmax);
    auto rng = std::default_random_engine(); 

    double total = 0.0; 
    for(int i = 0; i < N; i++) {
        double x = x_dist(rng); // Generate a value

        total += Func(x); 
    }  

    return (xmax - xmin) * total / N;
}
int main() {
    int N = 1; 

    for(int i = 0; i < 31; i++) {
        std::cout << "N = " << N << "\t\tintegral = " << Monte_Carlo(func, -2, 2, N) << endl; 
        N *= 2; // Double N
    }
}