拉格朗日插值法及代码

简介

在数值分析中,拉格朗日插值法是以法国十八世纪数学家约瑟夫·拉格朗日命名的一种多项式插值方法。许多实际问题中都用函数来表示某种内在联系或规律,而不少函数都只能通过实验和观测来了解。如对实践中的某个物理量进行观测,在若干个不同的地方得到相应的观测值,拉格朗日插值法可以找到一个多项式,其恰好在各个观测的点取到观测到的值。这样的多项式称为拉格朗日 (插值) 多项式。数学上来说,拉格朗日插值法可以给出一个恰好穿过二维平面上若干个已知点的多项式函数。拉格朗日插值法最早被英国数学家爱德华·华林于 1779 年发现,不久后 (1783 年) 由莱昂哈德·欧拉再次发现。1795 年,拉格朗日在其著作《师范学校数学基础教程》中发表了这个插值方法,从此他的名字就和这个方法联系在一起。拉格朗日插值时一种含义直观的代数插值方法。

定义

对某个多项式函数,已知有给定的 k + 1 个取值点:其中 xi 对应着自变量的位置,而 yi 对应着函数在这个位置的取值。
假设任意两个不同的 xi 都互不相同,那么应用拉格朗日插值公式所得到的拉格朗日插值多项式为:其中每个 li(x) 为拉格朗日基本多项式 (或称插值基函数),其表达式
为:
  l i ( x ) : = ∏ j = 0 , j ≠ i k x − x j x i − x j = x − x 0 x i − x 0 ⋯ x − x i − 1 x i − x i − 1 x − x i + 1 x i − x i + 1 ⋯ x − x k x i − x k \ l_i\left( x \right) :=\prod_{j=0,j\ne i}^k{\frac{x-x_j}{x_i-x_j}=\frac{x-x_0}{x_i-x_0}\cdots}\frac{x-x_{i-1}}{x_i-x_{i-1}}\frac{x-x_{i+1}}{x_i-x_{i+1}}\cdots \frac{x-x_k}{x_i-x_k}  li(x):=j=0,j=ikxixjxxj=xix0xx0xixi1xxi1xixi+1xxi+1xixkxxk
拉格朗日基本多项式 l i l_i li(x) 的特点是在 x i x_i xi 上取值为 1,在其它的点 x j x_j xj, i   ≠ \ \ne  = j 上取值为 0

实例

例 1. 令 f (x) =   x \ \sqrt{x}  x , 取插值节点为 f (2.56) = 1.6,f (2.89) = 1.7,f (3.24) = 1.8, 用两次拉格朗日插值计算   3 \ \sqrt{3}  3 的近似值。
解: 令插值节点 (x0, y0) = (2.56, 1.6),(x1, y1) = (2.89, 1.7),(x2, y2) = (3.24, 1.8), 故插值点
  f   ( 3 ) = ( x − x 1 ) ( x − x 2 ) ( x 0 − x 1 ) ( x 0 − x 2 ) y 0 + ( x − x 0 ) ( x − x 2 ) ( x 1 − x 0 ) ( x 1 − x 2 ) y 1 + ( x − x 0 ) ( x − x 1 ) ( x 2 − x 0 ) ( x 2 − x 1 ) y 2 \ f\ \left( 3 \right) =\frac{\left( x-x_1 \right) \left( x-x_2 \right)}{\left( x_0-x_1 \right) \left( x_0-x_2 \right)}y_0+\frac{\left( x-x_0 \right) \left( x-x _2\right)}{\left( x_1-x_0 \right) \left( x_1-x_2 \right)}y_1+\frac{\left( x-x_0 \right) \left( x-x_1 \right)}{\left( x_2-x_0 \right) \left( x_2-x_1 \right)}y_2  f (3)=(x0x1)(x0x2)(xx1)(xx2)y0+(x1x0)(x1x2)(xx0)(xx2)y1+(x2x0)(x2x1)(xx0)(xx1)y2
  f   ( 3 ) = ( 3 − 2.89 ) ( 3 − 3.24 ) ( 2.56 − 2.89 ) ( 2.56 − 3.24 ) × 1.6 + ( 3 − 2.56 ) ( 3 − 3.24 ) ( 2.89 − 2.56 ) ( 2.89 − 3.24 ) × 1.7 + ( 3 − 2.56 ) ( 3 − 2.89 ) ( 3.24 − 2.56 ) ( 3.24 − 2.89 ) × 1.8 \ f\ \left( 3 \right) =\frac{\left( 3-2.89 \right) \left( 3-3.24\right)}{\left( 2.56-2.89 \right) \left( 2.56-3.24\right)}\times1.6+\frac{\left( 3-2.56 \right) \left( 3-3.24\right)}{\left( 2.89-2.56 \right) \left( 2.89-3.24 \right)}\times1.7 \\ +\frac{\left( 3-2.56 \right) \left( 3-2.89 \right)}{\left( 3.24-2.56 \right) \left( 3.24-2.89\right)}\times1.8  f (3)=(2.562.89)(2.563.24)(32.89)(33.24)×1.6+(2.892.56)(2.893.24)(32.56)(33.24)×1.7+(3.242.56)(3.242.89)(32.56)(32.89)×1.8
因此   3 \ \sqrt{3}  3 ≈ 1.732。

以两点拉格朗日插值为例推导其系数公式

在这里插入图片描述
已知 φ 0 ( x ) φ_0(x) φ0(x) φ 1 ( x ) φ_1(x) φ1(x) 均为一次多项式,则可设
{ φ 0 ( x ) = a x + b φ 1 ( x ) = c x + d \left\{ \begin{array}{l} \varphi _0\left( x \right) =ax+b\\ \varphi _1\left( x \right) =cx+d\\ \end{array} \right. {φ0(x)=ax+bφ1(x)=cx+d
由以上 φ 0 ( x ) φ_0(x) φ0(x) φ 1 ( x ) φ_1(x) φ1(x) 满足的条件可得
{ φ 0 ( x ) = a x 0 + b = 1 φ 0 ( x ) = a x 1 + b = 0 \left\{ \begin{array}{l} \varphi _0\left( x \right) =ax_0+b=1\\ \varphi _0\left( x \right) =ax_1+b=0\\ \end{array} \right. {φ0(x)=ax0+b=1φ0(x)=ax1+b=0
{ φ 1 ( x ) = c x 0 + d = 0 φ 1 ( x ) = c x 1 + d = 1 \left\{ \begin{array}{l} \varphi _1\left( x \right) =cx_0+d=0\\ \varphi _1\left( x \right) =cx_1+d=1\\ \end{array} \right. {φ1(x)=cx0+d=0φ1(x)=cx1+d=1
解得
{ φ 0 ( x ) = x − x 1 x 0 − x 1 φ 0 ( x ) = x − x 0 x 1 − x 0 \left\{ \begin{array}{l} \varphi _0\left( x \right) =\frac{x-x_1}{x_0-x_1}\\ \\ \varphi _0\left( x \right) =\frac{x-x_0}{x_1-x_0}\\ \end{array} \right. φ0(x)=x0x1xx1φ0(x)=x1x0xx0
因此有
L 1 ( x ) = φ 0 ( x ) y 0 + φ 1 ( x ) = x − x 1 x 0 − x 1 y 0 + x − x 0 x 1 − x 0 y 1 L_1\left( x \right) =\varphi _0\left( x \right) y_0+\varphi _1\left( x \right) =\frac{x-x_1}{x_0-x_1}y_0+\frac{x-x_0}{x_1-x_0}y_1 L1(x)=φ0(x)y0+φ1(x)=x0x1xx1y0+x1x0xx0y1

代码

#include<iostream>
using namespace std;
double n,x[100],y[100],l[100] ;

void input()
{
	for(int i=0;i<n;i++) 
		cin>>x[i]>>y[i]; 
} 

double lagrange(double test)
{
	double re = 0;
	for(int i=0;i<100;i++) l[i]=1;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			if(j!=i)
				l[i] *=  (test-x[j])/(x[i]-x[j]);
		} 
		re += l[i]*y[i]; 
	}
	return re;
}

int main()
{
	
	for(int i=0;i<100;i++) l[i]=1; 
	cout<<"输入多少个点"<<endl;
	cin>>n;
	cout<<"输入插值点:"<<endl;
	input();
	double test; 
	cout<<"输入测试结点:"<<endl;
	while(1)
	{
		cin>>test; 
		double re = lagrange(test);
		cout<<"result: "<<re <<endl; 	
	 } 
	
	return 0;
}  

结果:
在这里插入图片描述

优缺点

  1. 插值基函数形式简单,但计算比较复杂;
  2. 当有新的插值点加入时,基函数要重新计算;
  3. 高次插值的精度不一定高;
  4. 当插值点比较多的时候,拉格朗日插值多项式的次数可能会很高,因此具有数值不稳定的特点,也就是说尽管在已知的几个点取到给定的数值,但在附近却会和“实际上”的值之间有很大的偏差。这类现象也被称为龙格现象,解决的办法是分段用较低次数的插值多项式。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值