1.拉格朗日插值法简介(引自维基百科)
对某个多项式函数,已知有给定的k + 1个取值点:
其中对应着自变量的位置,而对应着函数在这个位置的取值。
假设任意两个不同的xj都互不相同,那么应用拉格朗日插值公式所得到的拉格朗日插值多项式为:
其中每个为拉格朗日基本多项式(或称插值基函数),其表达式为:
2.重心拉格朗日插值法
重心拉格朗日插值法是拉格朗日插值法的一种改进。
定义重心权为,可将基本多项式改写为:
经过Jean-Paul Berrut, Lloyd N. Trefethen① 所给出的一系列推导可将L(x)改写为:
该公式被称作“真正的”重心拉格朗日插值公式,主要是为了与推导过程中由简化的基本多项式构成的公式相区分。该式相比一般的拉格朗日插值公式更易于计算,改变插值点的数量不需要重新计算,算法的复杂度降低了一个量级。
3.Java代码
简单的Java代码,可能存在潜在的错误。
import java.util.Scanner; public class BarycentricLagrangeInterpolation { private static double[] BELIE(double x[],double y[],double x0[]) { int m = x.length; int n = x0.length; double y0[] = new double[n]; for(int yi = 0;yi < n;yi ++) { double j = 0,k = 0,l = 0; int ic = 0; for(int ia = 0;ia < m;ia ++) { double w = 1; for(int ib = 0;ib < m;ib ++) { if(ia != ib) w /= (x[ia] - x[ib]); } System.out.println(w); k += (w / ((x0[yi] - x[ic]))) * y[ic]; l += (w / ((x0[yi] - x[ic]))); ic ++ ; j = k / l; } y0[yi] = j; } return y0; } public static void main(String[] args) { System.out.println("请输入给定的插值点数量:"); Scanner input = new Scanner(System.in); int m = input.nextInt(); System.out.println("请输入需求解的插值点数量:"); int n = input.nextInt(); double x[] = new double[m]; double y[] = new double[m]; double x0[] = new double[n]; System.out.println("依次输入给定的插值点:"); for(int i = 0;i < m;i ++){ x[i] = input.nextDouble(); } System.out.println("依次输入给定的插值点对应的函数值:"); for(int i = 0;i < m;i ++){ y[i] = input.nextDouble(); } System.out.println("依次输入需求解的插值点"); for(int i = 0;i < n;i ++){ x0[i] = input.nextDouble(); } double y0[] = BELIE(x, y, x0); System.out.println("运用重心拉格朗日插值法求解得:"); for(int i = 0;i < n;i ++){ System.out.println(y0[i] + " "); } System.out.println(); input.close(); } }
①可见于people.maths.ox.ac.uk/trefethen/barycentric.pdf