我需要使用拉格朗日interpolation polynomial来计算多项式的系数,作为我的作业,我决定在Javascript中这样做。
这里是拉格朗日多项式(L(x))
的定义
拉格朗日基多项式定义如下
计算特定X(W(x)函数)的y值很简单,但我需要计算多项式的系数([a0,a1,...,an]的数组)我需要这样做n< = 10但是拥有任意n会很好,然后我可以将该函数放入horner函数并绘制该多项式。
我有在第一个等式中计算分母的函数
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;
};
}
任何人都知道这样做的算法,或者想知道如何计算这些系数
答案 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