c ++编译非常慢 二维向量
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;
答案 0 :(得分:4)
此代码集成了2维[(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点的精确结果。 这个正交是最简单的一个。 我的测试代码是here。
一维集成:
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 最后,对于数值积分,有各种正交函数。
如果在此高斯被积中插入函数,则建议使用Hermite正交或快速高斯变换(FGT)。