如何使用拉格朗日插值计算多项式系数

时间:2012-03-25 14:27:54

标签: javascript polynomial-math

我需要使用拉格朗日interpolation polynomial来计算多项式的系数,作为我的作业,我决定在Javascript中这样做。

这里是拉格朗日多项式(L(x))

的定义

enter image description here

拉格朗日基多项式定义如下

enter image description here

计算特定X(W(x)函数)的y值很简单,但我需要计算多项式的系数([a0,a1,...,an]的数组)我需要这样做n< = 10但是拥有任意n会很好,然后我可以将该函数放入horner函数并绘制该多项式。

enter image description here

我有在第一个等式中计算分母的函数

function denominator(i, points) {
   var result = 1;
   var x_i = points[i].x;
   for (var j=points.length; j--;) {
      if (i != j) {
        result *= x_i - points[j].x;
      }
   }
   return result;
}

和使用horner方法返回y的函数(我也使用画布绘制函数)

function horner(array, x_scale, y_scale) {
   function recur(x, i, array) {
      if (i == 0) {
         return x*array[0];
      } else {
         return array[i] + x*recur(x, --i, array);
      }
   }
   return function(x) {
      return recur(x*x_scale, array.length-1, array)*y_scale;
   };
}

任何人都知道这样做的算法,或者想知道如何计算这些系数

3 个答案:

答案 0 :(得分:8)

嗯,你可以用天真的方式做到这一点。用其系数数组表示多项式,即数组

[a_0,a_1,...,a_n]

对应a_0 + a_1*X + ... + a_n*X^n。我对JavaScript不好,所以伪代码必须这样做:

interpolation_polynomial(i,points)
    coefficients = [1/denominator(i,points)]
    for k = 0 to points.length-1
        if k == i
            next k
        new_coefficients = [0,0,...,0] // length k+2 if k < i, k+1 if k > i
        if k < i
            m = k
        else
            m = k-1
        for j = m downto 0
            new_coefficients[j+1] += coefficients[j]
            new_coefficients[j] -= points[k]*coefficients[j]
        coefficients = new_coefficients
    return coefficients

以常数多项式1/((x_1-x_0)* ... *(x_i-x_{i-1})*(x_i-x_{i+1})*...*(x_i-x_n))开头,并与所有X - x_k的{​​{1}}相乘。因此,给出L i 的系数,然后你只需将它们乘以y i (你可以通过将k != i初始化为coefficients来实现。你传递y值作为参数)并最终将所有系数加在一起。

y_i/denominator(i,points)

计算每个L i 是O(n²),因此总计算为O(n³)。

更新:在你的jsFiddle中,你在多项式乘法循环中出现错误,除了(现在已经纠正的)错误以及我做的起始索引,它应该是

polynomial = [0,0,...,0] // points.length entries
for i = 0 to points.length-1
    coefficients = interpolation_polynomial(i,points)
    for k = 0 to points.length-1
        polynomial[k] += y[i]*coefficients[k]

由于您在测试时递减for (var j= (k < i) ? (k+1) : k; j--;) { new_coefficients[j+1] += coefficients[j]; new_coefficients[j] -= points[k].x*coefficients[j]; } ,因此需要更高一些。

这还没有产生正确的插值,但它至少比以前更明智。

此外,在您的j功能

horner

你将最高系数乘以function horner(array, x_scale, y_scale) { function recur(x, i, array) { if (i == 0) { return x*array[0]; } else { return array[i] + x*recur(x, --i, array); } } return function(x) { return recur(x*x_scale, array.length-1, array)*y_scale; }; } 两次,它应该是

x

代替。但是,仍然没有好结果。

Update2:最终的拼写错误修复,以下工作:

if (i == 0) {
    return array[0];
}

答案 1 :(得分:1)

如果使用“ Beginner's guide to mapping simplexes affinely ”中“拉格朗日插值”部分中介绍的拉格朗日插值的矩阵形式,则可以相对容易地找到拉格朗日插值多项式的系数。恐怕,我不知道JavaScript无法为您提供适当的代码,但是我稍微使用了Python,也许以下内容可以提供帮助(对不起,不好的代码风格-我是数学家,而不是程序员)

import numpy as np
# input
x = [0, 2, 4, 5]  # <- x's
y = [2, 5, 7, 7]  # <- y's
# calculating coefficients
M = [[_x**i*(-1)**(i*len(x)) for _x in x] for i in range(len(x))]
C = [np.linalg.det((M+[y]+M)[d:d+len(x)]) for d in range(len(x)+1)]
C = (C / C[0] * (-1)**(len(x)+1) )[1:]
# polynomial lambda-function
poly = lambda _x: sum([C[i] * _x**i for i in range(len(x))])
# output and tests
print("Coefficients:\n", C)
print("TESTING:")
for _x, _y in zip(x, y):
    result = "[OK]" if np.allclose(_y, poly(_x)) else "[ERROR]"
    print(_x, " mapped to: ", poly(_x), " ; expected: ", _y, result)

此代码计算Lagrange插值多项式的系数,打印出来,并测试将给定的x映射到预期的y中。您可以使用Google colab测试此代码,因此无需安装任何程序。可能您可以将其翻译为JS。

答案 2 :(得分:0)

此代码将从常数项开始确定系数。

_M_construct