[计算机数值积分]龙贝格公式求数值积分

梯形递推的变步长求积公式虽然算法简单,但精度低,收敛的速度慢,因此,研究收敛速度快、精度高的龙贝格算法显得尤为重要。

例:用龙贝格算法求f(x) = sin(x) / x 在区间[0,1]的数值积分,精度要求为1e-6.

  • 加工流程:

在这里插入图片描述

  • 程序框图设计:

在这里插入图片描述

  • 运行示例:

在这里插入图片描述

  • 源码:
#include<iostream>
#include<cmath>
double f(double x);   //自定义函数

using namespace std;

int main(void)
{
    
    
	double a, b, accuracy;   //a为区间下限,b为区间上限,accuracy为精度

	cout << "请输入积分区间:";   //输入提示
	cin >> a >> b;

	cout << "请输入精度:";   //输入提示
	cin >> accuracy;

	double h;   //步长

	h = b - a;  

	double T1, T2;   //T1:二分前的梯形法积分值;T2:二分后的梯形法积分值;

	T1 = h / 2 * (1 + f(b));    
	T2 = 0;

	int k = 1;  //记录二分次数

	cout << "T" << pow(2, 0) << " = " << T1 << endl;

	double S1, S2;   //对T1与T2加权平均,得辛普森积分值
	double C1, C2;   //对S1与S2加权平均,得柯特斯积分值
	double R1, R2;   //对C1,C2加权平均,得龙贝格积分值
	int flag = 1;   //flag作为循环控制标志性变量

	while (flag == 1)
	{
    
    
		double sum = 0;  //各分点的函数值和
		double x = a + h / 2;   //分点值

		while (x < b)   //在区间上限范围内求各分点的函数值和
		{
    
    
			sum += f(x);   
			x += h;   
		}

		T2 = T1 / 2 + h / 2 * sum;    //计算梯形序列得下一个二分结果
		cout << "T" << pow(2, k) << " = " << T2 << endl;

		S2 = T2 + 1.0 / 3 * (T2 - T1);   //线性组合外推值simpson
		cout << "S" << pow(2, k - 1) << " = " << S2 << endl;

		if (k == 1)   //至少外推2次得出S1,S2
		{
    
    
			k++;
			h /= 2;
			T1 = T2;
			S1 = S2;
			continue;
		}
		else
		{
    
    
			C2 = S2 + 1.0 / 15 * (S2 - S1);  //线性组合外推值Cotes
			cout << "C" << pow(2, k - 2) << " = " << C2 << endl;

			if (k == 2)   //至少外推3次得出C1,C2
			{
    
    
				C1 = C2;
				k++;
				h /= 2;
				T1 = T2;
				S1 = S2;
				continue;
			}
			else
			{
    
    
				R2 = C2 + 1.0 / 63 * (C2 - C1);   //线性组合外推至Romberg
				cout << "R" << pow(2, k - 3) << " = " << R2 << endl;

				if (k == 3)   //至少外推4次得出R1,R2
				{
    
    
					R1 = R2;
					C1 = C2;
					k++;
					h /= 2;
					T1 = T2;
					S1 = S2;
					continue;
				}
				else if (abs(R2 - R1) >= accuracy)   //精度仍然不符合要求,继续二分步长、继续外推
				{
    
    
					R1 = R2;
					C1 = C2;
					k = k + 1;
					h = h / 2;
					T1 = T2;
					S1 = S2;
				}
				else   //精度符合要求,修改flag为0,跳出while循环
				{
    
    
					flag = 0;
					cout << "Romber算法求得数值积分结果为:" << R2 << endl;
				}
			}
		}
	}

	return 0;
}

double f(double x)   //自定义被积函数
{
    
    
	double result;

	result = sin(x) / x;

	return result;
}

猜你喜欢

转载自blog.csdn.net/weixin_51008866/article/details/116081534