C++ 蒙特卡洛积分 : How to run code multiple times without summing the results?

标签 c++ integration montecarlo

这是我更改之前的代码以包含多次运行它的能力:

#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <math.h>
#include <random>
#include <iomanip>
#include <vector>

using namespace std; 

int main () {
    double vol;
    double hit;
    int samples;
    int i, j;
    double sum;
    double pt;
    double actual_vol;
    const double PI = 2.0*atan2(1.0,0.0);
    double abs_err;
    double rel_err;

    random_device dev;
    default_random_engine e{ dev() };
    uniform_real_distribution<double> u{0.0,1.0};

    samples = 1000000 * dim;

    actual_vol = pow(PI, double(dim/2.0)) / exp(lgamma(double(dim/2.0)+1.0));

    for (i = 0; i < samples; i++) {
            sum = 0;
            for (j = 0; j < dim; j++) {
                    pt = 2*(u(e)-0.5);
                    sum += pt*pt;
            }
            if (sqrt(sum) < 1) {
                    hit += 1;
            }
    }

    vol = ( pow(2,dim) * hit ) / samples;
    abs_err = fabs( actual_vol - vol);
    rel_err = abs_err / actual_vol;

    cout << "Average volume of your sphere: " << setprecision(7) << vol << endl;
    cout << "Actual volume: " << setprecision(7) << actual_vol << endl;
    cout << "Absolute Error: " << setprecision(7) << abs_err << endl;
    cout << "Relative Error: " << setprecision(7) << rel_err << endl;
}

我会得到看起来像这样的正确输出:

Average volume of your sphere: 3.140924
Actual volume: 3.141593
Absolute Error: 0.0006686536
Relative Error: 0.000212839

现在,当我更改它以便我可以调用该函数并多次运行它时,使用以下代码:

#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <math.h>
#include <random>
#include <iomanip>
#include <vector>

using namespace std;

double monte_carlo (int dim) {
    double vol;
    double hit;
    int samples;
    int i, j;
    double sum;
    double pt;
    double actual_vol;
    const double PI = 2.0*atan2(1.0,0.0);
    double abs_err;
    double rel_err;

    random_device dev;
    default_random_engine e{ dev() };
    uniform_real_distribution<double> u{0.0,1.0};

    samples = 1000000 * dim;

    actual_vol = pow(PI, double(dim/2.0)) / exp(lgamma(double(dim/2.0)+1.0));

    for (i = 0; i < samples; i++) {
            sum = 0;
            for (j = 0; j < dim; j++) {
                    pt = 2*(u(e)-0.5);
                    sum += pt*pt;
            }
            if (sqrt(sum) < 1) {
                    hit += 1;
            }
    }

    vol = ( pow(2,dim) * hit ) / samples;
    abs_err = fabs( actual_vol - vol);
    rel_err = abs_err / actual_vol;

    cout << "Average volume of your sphere: " << setprecision(7) << vol << endl;
    cout << "Actual volume: " << setprecision(7) << actual_vol << endl;
    cout << "Absolute Error: " << setprecision(7) << abs_err << endl;
    cout << "Relative Error: " << setprecision(7) << rel_err << endl;
}

int main (int argc, char* argv[]) {

    int dim = 0;
    int runs = 0;
    int i;

    dim =  atoi(argv[1]);
    runs = atoi(argv[2]);

    for (i = 0; i < runs; i++) {
            monte_carlo(dim);
    }

    return 0;
}

我得到这些结果,现在将以前的值与当前值相加,这不是我想要的:

Average volume of your sphere: 3.141764
Actual volume: 3.141593
Absolute Error: 0.0001713464
Relative Error: 5.454126e-05
Average volume of your sphere: 6.283674
Actual volume: 3.141593
Absolute Error: 3.142081
Relative Error: 1.000156
Average volume of your sphere: 9.427502
Actual volume: 3.141593
Absolute Error: 6.285909
Relative Error: 2.000867
Average volume of your sphere: 12.56937
Actual volume: 3.141593
Absolute Error: 9.427775
Relative Error: 3.000954
Average volume of your sphere: 15.71272
Actual volume: 3.141593
Absolute Error: 12.57113
Relative Error: 4.001515
Average volume of your sphere: 18.85378
Actual volume: 3.141593
Absolute Error: 15.71219
Relative Error: 5.001345
Average volume of your sphere: 21.99504
Actual volume: 3.141593
Absolute Error: 18.85345
Relative Error: 6.001239

您会注意到球体平均体积的第一个值约为 3.14,然后是它的第二个实例,现在是 6.28(或第一个实例的两倍),第三个实例是 9.42(大约是第一个实例的三倍一)等

它应该做的是在每次运行时重新计算,并且每个计算的值都应该徘徊在 3.14 左右。如何让它停止对上一次运行的值求和?

谢谢!!

最佳答案

这可能是因为您从未重新初始化变量。

您也有强烈的“旧”C 偏见(C header 、atoi 的用法、fabs...),在需要时声明您的变量,并且你的路径也总是相似的,因为你使用相同的随机数生成器和相同的种子(默认构造)。

仍然,对于你的问题:

double hit = 0;
double samples = 0;

等等。

同样对于 PI,如果您有提升,请使用它的常量,而不是以低于它所能提供的精度重新计算它。

关于C++ 蒙特卡洛积分 : How to run code multiple times without summing the results?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53671180/

相关文章:

php - 如何将 C++ 应用程序集成到 PHP 网站中?

python - 如何使用 NumPy/SciPy 进行简单的高斯混合采样和 PDF 绘图?

c++ - 返回二维 vector 的结束索引

php - 如何保护网站的 Paypal 集成

c++ - 访问函数变体时出现 "Invalid conversion"错误

java - 集成 Play 框架 2.0 和 Spring 框架

python - 我的蒙特卡罗模拟 RNG 中某处出错?

python - 在 Python 中模拟伊辛模型

c++ - 在 C 中更改指向数组的指针

c++ - 什么时候计算右值?