1

我正在编写一个使用梯形规则递归计算积分的函数。对于区间(a,b)上的一些f(x),方法是计算边为(ba)的大梯形的面积,然后与将区间分成n部分后形成的小梯形的总和进行比较。如果差值大于某个给定误差,则对每个小梯形再次调用该函数并将结果求和。如果差值较小,则返回两个值的算术平均值。

该函数有两个参数,一个指向要集成的函数的函数指针和一个对辅助结构的常量引用,该辅助结构包含区间 (a,b)、分区数量等信息:

struct Config{
double min,max;
int partitions;
double precision;
};

当我想在每次迭代中更改分区数量时,问题就出现了,现在让我们说只是增加一个。如果不求助于当前的递归深度,我认为没有办法做到这一点:

integrate(const Config &conf, funptr f){

double a=conf.min,b=conf.max;
int n=conf.partitions;

//calculating the trapezoid areas here

if(std::abs(bigTrapezoid-sumOfSmallTrapezoids) > conf.precision){

double s=0.;
Config configs = new Config[n];
int newpartitions = n+(calls);

for(int i=0; i < n;++i){ 
    configs[i]={ a+i*(b-a)/n , a+(i+1)*(b-a)/n , newpartitions};
    s+=integrate(configs[i],f);
}

delete [] configs;
return s; }

else{ 
return 0.5*(bigTrapezoid+sumOfSmallTrapezoids);}
}

我在这里缺少的部分当然是一种查找(调用)的方法。我试过做类似于这个答案的事情,但它不起作用,事实上它会冻结电脑,直到 makefile 杀死进程。但也许我做错了。我不想向函数添加额外的参数或向结构添加额外的变量。我应该如何进行?

4

2 回答 2

2

您无法“找到” calls,但您绝对可以自己传递,如下所示:

integrate(const Config &conf, funptr f, int calls=0) {
    ...
    s+=integrate(configs[i],f, calls+1);
    ...
}
于 2013-11-09T14:03:35.853 回答
1

在我看来,'int newpartitions = n + 1;' 就够了,不是吗?在每个递归级别,分区的数量都会增加一个。假设 conf.partitions 从 1 开始。如果例程需要向下递归一个新级别,则 newpartitions 为 2,您将构建 2 个新的 Config 实例,每个实例都以“2”作为分区值。向下递归另一个级别,newpartitions 为 3,您构建 3 个配置,每个配置都以“3”作为“分区”,依此类推。

这里的诀窍是确保您的代码足够健壮以避免无限递归。

顺便说一句,对我来说,对循环后必须销毁的 Config 实例使用动态分配似乎效率低下。为什么不在循环内的堆栈上构建单个 Config 实例?您的代码应该以这种方式运行得更快。

于 2013-11-09T22:02:18.127 回答