首页 > 解决方案 > 当我设置大数字 n 时,我的代码编译速度非常慢。我不知道如何设置循环

问题描述

c++ 为 2d 向量编译非常慢

std::vector< vector<double>  > V(n, vector<double> (n));
double sum2=0;

for(int i=0; i<n; i++)
{

    double xai=xa1+i*dxa;
    double dxr=(double)(xr2-xr1)/n;
    double sum1=0;
    for(int j=0; j<n; j++){

        double xri=xr1+dxr*j;
        V[i][j]=fun(xri,xai);
        double rect1=V[i][j]*dxr;
        sum1+=rect1;
    }
    double rect2=sum1*dxa;
    sum2+=rect2;    
}
return sum2;

标签: c++c++11

解决方案


  • 此代码是二维积分 [(1/2*pi)*exp(-xr^2/2)*exp(-xa^2/2)]。

  • 这个方程的积分在无穷大时等于 1,所以在 C++ 中,我们必须增加限制和 n 才能得到等于 1 的结果作为理论。

如果我们将牛顿-科茨求积应用于无限积分

在此处输入图像描述

,我们需要切断这个积分的上下边界。被积函数在分界点处的小到可以忽略不计。您选择了哪个值?

你的问题的积分是高斯的并且像这样迅速减少,

 exp(-10*10/2) ~ 1.93 * 10^(-22)

这在目前的整合中可以忽略不计。因此,如果我们分别用-10和+10截断上下边界,并在这个范围内设置足够多的点,我们应该得到精确的结果。

实际上,我使用以下梯形求积得到了 100x100 点的精确结果。这个正交是最简单的。我的测试代码在这里

一维整合:

template<typename F>
double integrate_trapezoidal(F func, std::size_t n, double lowerBnd, double upperBnd)
{
    if(lowerBnd == upperBnd){
        return 0.0;
    }

    auto integral = 0.0;
    
    auto x = lowerBnd;
    const auto dx = (upperBnd - lowerBnd)/n;

    auto left = func(x);
    for(std::size_t i = 0; i<n; ++i)    
    {
        x += dx;
        const auto right = func(x);
        integral += (left + right);
        left = right;
    }
    
    integral *= (0.5*dx);
    
    return integral;
}

二维整合:

template<typename F>
double integrate_trapezoidal_2dim(
    F func_2dim,
    std::size_t n,
    double x_lowerBnd, double x_upperBnd,
    double y_lowerBnd, double y_upperBnd)
{
    auto func = [&](double x)
    {
        return integrate_trapezoidal(
            std::bind(func_2dim, x, std::placeholders::_1), 
            n, y_lowerBnd, y_upperBnd); 
    };
    
    return integrate_trapezoidal(func, n, x_lowerBnd, x_upperBnd);
}

我担心你设置了有限但非常大的上下边界。在这种情况下,您需要在 -10 < x < +10 的范围内设置许多点来增加品脱的数量。

最后,数值积分有多种求积方法。如果你在这个高斯被积函数中插入一些函数,那么应该推荐 Hermite 正交或快速高斯变换 (FGT)。


推荐阅读