算法复习之分治与贪心(3)

一维数值积分

        给出一维函数f(x),计算\int _{a}^b f(x)dx

解决方法

梯形近似法

        我们想到的对于无闭式解的一维数值积分的求解方法,最常规的就是将区间切分为n段,将n段梯形的面积相加可以近似为函数在这一区间上的积分值

\int_{x_0}^{x_1} P(x)dx=\frac{x_1-x_0}{2}(f(x_0)+f(x_1))

        不过很显然,这种近似的求解方法只适用于一些平缓的函数,并且还跟区间切分的长度有着十分密切的相关性,并不能解决全部的一维数值积分问题,所以我们应该如何优化这一方法呢?

        对于利用梯形面积近似积分的表达式,可以看到其实相当于是在两个点之间构建了一个线性函数,这种方法叫做线性插值(一次插值)。

拉格朗日插值多项式

        通过n+1个不同的点(x_i,y_i),可以确定一个n阶多项式函数的全部系数

A(x)=\sum_{i=0}^{n-1} f(x_i)\prod_{j\neq i} \frac{(x-x_j)}{(x_i-x_j)}

        利用这个思想,我们便可以通过较多地在区间内选取点,构造更高维的多项式函数,这样就可以使拟合结果无限接近原函数。 

优化一:二次插值

        在梯形近似法中,由于其为一次插值,所以对于区间内每一段都是一条线段(由两个端点唯一确定),但是相对于原函数的拟合程度却欠佳,所以我们在区间中构建一个二次函数,优化其拟合程度。

        我们目前考虑到 [a,b] 区间内 a,b,m(区间中点)三个点,根据拉格朗日插值多项式,我们可以构建一个二次多项式函数:

P(x)=f(a)\frac{(x-m)(x-b)}{(a-m)(a-b)}+f(m)\frac{(x-a)(x-b)}{(m-a)(m-b)}+f(b)\frac{(x-a)(x-m)}{(b-a)(b-m)} 

         利用这个二次插值函数求积分来近似估计原函数在当前区间的积分值

\int_{a}^{b}f(x)dx\approx \int_{a}^{b}P(x)dx

        此时发现对于二次插值函数求积分是一件较为困难的事情,所以我们引出一个快速求解积分的方法,即辛普森积分法

\int_{a}^{b}P(x)dx=\frac{b-a}{6}(f(a)+4f(m)+f(b)) 

        这样我们利用已知的函数值就可以快速计算出最后的积分结果。

优化二:自适应辛普森算法

        在优化一中,我们虽然提升了算法的近似效果,但是很快会发现一个问题,当原函数在某段区间上的变化趋势近似于一条直线段时,显然我们使用梯形近似法要比二次插值法更好,并且只需要拆分出一个很大粒度的区间段即可,从此引发了一个比较关键的问题,即在插值拟合的过程中,需要进行区间等分么?

        很显然,刚才的例子证明了,区间其实是不需要等分的,根据区间的变化我们可以选择不同的插值方法,最后组合在一起才是效果最好的,所以我们对于每一段区间的拟合程度限定一个误差上限即可。

struct Func{
	double value;
	Func(int x) {};
	double getValue() {
		return value;
	};
};

double function(int x) {
	return Func(x).getValue();
}

double adaptSimpson(int left, int right, double threshold) {
	int mid = left + (right - left) / 2;
	double leftHalfValue = simpson(left, mid);
	double rightHalfValue = simpson(mid, right);
	if (abs(leftHalfValue + rightHalfValue - simpson(left, right)) < threshold) {
		return simpson(left, right);
	}
	return adaptSimpson(left, mid, threshold) + adaptSimpson(mid, right, threshold);
}

double simpson(int left, int right) {
	double res = (right - left) / 6 * (function(left) + function(right) + function((left + right) / 2));
	return res;
}

时间复杂度

        此算法的时间复杂度(函数执行次数),由原函数在当前的划分区间 [a, b] 内的变化趋势以及手动定义的误差阈值有关,可以通过不断调整参数来使其达到较为良好的计算水平。

仍然存在的问题

        以上我们探讨的是关于一维数值积分的相关问题,但是在现实情况中,我们往往面对的是计算高维函数的数值积分,这种情况该如何处理呢?请听下回分解。 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小糖豆豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值