插值型求积公式(C++)

插值型求积公式是一种用于计算定积分的数学方法. 它基于把未知的定积分分解为可求解的函数值的积分, 然后将函数拟合为多项式或其他函数, 最后使用拟合函数去近似定积分. 由于拟合的函数具有更好的变化性, 效果更好, 而改进的插值型求积公式又能更好地拟合变化的函数, 因此它们被认为是计算积分的有效方法.

说明

插值型求积公式要求输入解的定积分 ∫ a b f ( x ) d x \displaystyle\int_a^b f(x){\rm d}x abf(x)dx, 插值节点的个数 n n n, 插值节点的选择方法, 以及插值函数的类型, 最终输出定积分的近似值. 这种求积方法导出的公式也被称为Newton-Cotes求积公式. 其算法可描述如下:

  • 根据插值节点的选择方法, 在区间 [ a , b ] [a,b] [a,b]上选择 n + 1 n+1 n+1个插值节点 x 0 , x 1 , ⋯   , x n x_0,x_1,\cdots,x_n x0,x1,,xn.
  • 根据插值节点和插值函数的类型, 构造插值函数 P ( x ) P(x) P(x).
  • 计算插值函数的积分 ∫ a b P ( x ) d x \displaystyle\int_a^bP(x){\rm d}x abP(x)dx.

我们可以通过插值公式计算出当 n n n较小时的公式如下:
∫ a b f ( x ) d x ≈ b − a 2 [ f ( a ) + f ( b ) ] \int_a^bf(x){\rm d}x\approx\frac{b-a}2[f(a)+f(b)] abf(x)dx2ba[f(a)+f(b)]
∫ a b f ( x ) d x ≈ b − a 6 [ f ( a ) + 4 f ( b + a 2 ) + f ( b ) ] \int_a^b f(x)\text{d}x\approx\dfrac{b-a}{6}\Big[f(a)+4f\Big(\dfrac{b+a}{2}\Big)+f(b)\Big] abf(x)dx6ba[f(a)+4f(2b+a)+f(b)]
∫ a b f ( x ) d x ≈ b − a 8 [ f ( x 0 ) + 3 f ( x 1 ) + 3 f ( x 2 ) + f ( x 3 ) ] \int_a^b f(x)\text{d}x\approx\dfrac{b-a}{8}\left[f(x_0)+3f(x_1)+3f(x_2)+f(x_3)\right] abf(x)dx8ba[f(x0)+3f(x1)+3f(x2)+f(x3)]
∫ a b f ( x ) d x ≈ b − a 90 [ 7 f ( x 0 ) + 32 f ( x 1 ) + 12 f ( x 2 ) + 32 f ( x 3 ) + 7 f ( x 4 ) ] \int_a^b f(x)\text{d}x\approx\dfrac{b-a}{90}\big[7f(x_{0})+32f(x_{1})+12f(x_{2})+32f(x_{3})+7f(x_{4})\big] abf(x)dx90ba[7f(x0)+32f(x1)+12f(x2)+32f(x3)+7f(x4)]

上述公式依次被称为梯形公式, Simpson公式, Newton公式和Cotes公式.

在实际应用中, 插值型求积公式通常会选择合适的插值节点和插值函数类型, 以使得近似值尽可能接近真实值. 此外, 还可以通过增加插值节点的个数 n n n来提高近似精度. 但当插值节点增多时, 初始数据的误差引起计算结果的误差的增大, 即计算不稳定, 因此, 高阶Newton-Cotes公式不稳定. 所以当节点较多时, 需要寻求精度更高的求积公式.

代码实现

首先包含头文件:

#include <functional>
using std::function;

梯形公式:

/*
 * 梯形公式
 * f:被积函数
 * a:积分下限
 * b:积分上限
 */
double trapezoid(function<double(double)> f, const double &a, const double &b)
{
    if (a >= b)
        throw "区间上限小于区间下限!";
    double fa(f(a));
    if (isnan(fa))
        throw "积分下限处函数值无法计算!";
    double fb(f(b));
    if (isnan(fb))
        throw "积分上限处函数值无法计算!";
    return (b - a) * (fa + fb) / 2;
}

Simpson公式:

/*
 * Simpson公式
 * f:被积函数
 * a:积分下限
 * b:积分上限
 */
double Simpson(function<double(double)> f, const double &a, const double &b)
{
    if (a >= b)
        throw "区间上限小于区间下限!";
    double fa(f(a));
    if (isnan(fa))
        throw "积分下限处函数值无法计算!";
    double fb(f(b));
    if (isnan(fb))
        throw "积分上限处函数值无法计算!";
    double fm(f((a + b) / 2));
    if (isnan(fm))
        throw "积分区间中点处函数值无法计算!";
    return (b - a) * (fa + fb + 4 * fm) / 6;
}

Newton公式:

/*
 * Newton公式
 * f:被积函数
 * a:积分下限
 * b:积分上限
 */
double Newton(function<double(double)> f, const double &a, const double &b)
{
    if (a >= b)
        throw "区间上限小于区间下限!";
    double fa(f(a));
    if (isnan(fa))
        throw "积分下限处函数值无法计算!";
    double fb(f(b));
    if (isnan(fb))
        throw "积分上限处函数值无法计算!";
    double d0(b - a), d(d0 / 3), f1(f(a + d));
    if (isnan(f1))
        throw "积分区间左三等分点处函数值无法计算!";
    double f2(f(b - d));
    if (isnan(f2))
        throw "积分区间右三等分点处函数值无法计算!";
    return d0 * (fa + fb + (f1 + f2) * 3) / 8;
}

Cotes公式:

/*
 * Cotes公式
 * f:被积函数
 * a:积分下限
 * b:积分上限
 */
double Cotes(function<double(double)> f, const double &a, const double &b)
{
    if (a >= b)
        throw "区间上限小于区间下限!";
    double fa(f(a));
    if (isnan(fa))
        throw "积分下限处函数值无法计算!";
    double fb(f(b));
    if (isnan(fb))
        throw "积分上限处函数值无法计算!";
    double d0(b - a), d(d0 / 4), x(a + d), f1(f(x));
    if (isnan(f1))
        throw "积分区间左四等分点处函数值无法计算!";
    double fm(f(x += d));
    if (isnan(fm))
        throw "积分区间中点处函数值无法计算!";
    double f2(f(x += d));
    if (isnan(f2))
        throw "积分区间右四等分点处函数值无法计算!";
    return d0 * (7 * (fa + fb) + 32 * (f1 + f2) + 12 * fm) / 90;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

zsc_118

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

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

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

打赏作者

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

抵扣说明:

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

余额充值