我正在编写一个使用梯形规则递归计算积分的函数。对于区间(a,b)上的一些f(x),该方法是计算具有边(b-a)的大梯形的面积,然后将其与将间隔分成n个部分之后形成的小梯形的总和进行比较。如果差值大于某个给定误差,则对每个小梯形再次调用该函数,并将结果相加。如果差异较小,则返回两个值的算术平均值。
该函数有两个参数,一个是要集成的函数的函数指针,另一个是辅助结构的常量引用,它包含间隔(a,b),分区数等信息: / p>
struct Config{
double min,max;
int partitions;
double precision;
};
当我想在每次迭代时更改分区数量时出现问题,暂时让我们说只增加1。如果不诉诸于当前的重复深度,我认为没有办法做到这一点:
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);}
}
我在这里缺少的部分当然是一种寻找(呼叫)的方法。我尝试过类似于this的答案,但它不起作用,事实上它会冻结pc,直到makefile终止进程。但也许我做错了。我不想在函数中添加额外的参数或者为结构添加额外的变量。我该怎么办?
答案 0 :(得分:2)
你不能“找到”calls
,但你可以自己传递它,就像这样:
integrate(const Config &conf, funptr f, int calls=0) {
...
s+=integrate(configs[i],f, calls+1);
...
}
答案 1 :(得分:1)
在我看来'int newpartitions = n + 1;'会不够的,不是吗?在每个递归级别,分区数增加1。假设conf.partitions从1开始。如果例程需要递归到新的级别,则newpartitions为2,并且您将构建2个新的Config实例,每个实例的“2”作为分区的值。递减到另一个级别,newpartitions是3,你构建3个Configs,每个都有'3'作为'分区',依此类推。
这里的技巧是确保您的代码足够强大,以避免无限递归。
顺便说一句,对于在循环之后必须销毁的Config实例使用动态分配似乎效率低下。为什么不在循环内的堆栈上构建一个Config实例?你的代码应该以这种方式运行得更快。