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

标签 javascript polynomial-math

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

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

enter image description here

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

enter image description here

计算特定 X 的 y 值(W(x) 函数)很简单,但我需要计算多项式的系数([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 的函数(我也有使用 canvas 的绘图函数)

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;
   };
}

任何人都知道执行此操作的算法,或者知道如何计算这些系数

最佳答案

好吧,你可以用天真的方法来做。用系数数组表示多项式,数组

[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)) 并为所有 k != i 乘以 X - x_k。这样就给出了 Li 的系数,然后您只需将它们与 yi 相乘(您可以通过将 coefficients 初始化为 y_i/denominator(i,points) 如果您将 y 值作为参数传递)并最终将所有系数相加。

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]

计算每个Li是O(n²),所以总计算是O(n³)。

更新:在你的 jsFiddle 中,你在多项式乘法循环中有一个错误,除了(现在更正)我做的起始索引错误,它应该是

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乘以最高系数两次,它应该是

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

相反。不过,仍然没有什么好结果。

更新 2: 最终的拼写错误修复,以下工作:

function horner(array, x_scale, y_scale) {
   function recur(x, i, array) {
      if (i == 0) {
         return 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;
   };
}

// initialize array
function zeros(n) {
   var array = new Array(n);
   for (var i=n; i--;) {
     array[i] = 0;
   }
   return array;
}

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;
      }
   }
    console.log(result);
   return result;
}

// calculate coefficients for Li polynomial
function interpolation_polynomial(i, points) {
   var coefficients = zeros(points.length);
    // alert("Denominator " + i + ": " + denominator(i,points));
   coefficients[0] = 1/denominator(i,points);
    console.log(coefficients[0]);
    //new Array(points.length);
   /*for (var s=points.length; s--;) {
      coefficients[s] = 1/denominator(i,points);
   }*/
   var new_coefficients;

   for (var k = 0; k<points.length; k++) {
      if (k == i) {
        continue;
      }
      new_coefficients = zeros(points.length);
       for (var j= (k < i) ? k+1 : k; j--;) {
         new_coefficients[j+1] += coefficients[j];
         new_coefficients[j] -= points[k].x*coefficients[j];
      }   
      coefficients = new_coefficients;
   }
   console.log(coefficients);
   return coefficients;
}

// calculate coefficients of polynomial
function Lagrange(points) {
   var polynomial = zeros(points.length);
   var coefficients;
   for (var i=0; i<points.length; ++i) {
     coefficients = interpolation_polynomial(i, points);
     //console.log(coefficients);
     for (var k=0; k<points.length; ++k) {
       // console.log(points[k].y*coefficients[k]);
        polynomial[k] += points[i].y*coefficients[k];
     }
   }
   return polynomial;
}

关于javascript - 如何使用拉格朗日插值计算多项式的系数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9860937/

相关文章:

javascript - Mongoose Delete 和 Express app.delete 有什么区别

java - tomcat 7.0.50 java websocket 实现给出 404 错误

r - 如何通过我的数据拟合平滑曲线?

c - 拟合多项式趋势线的好包

javascript - 查看不同的 HTML 页面?

javascript - 从 AJAX 请求中抓取 JSON 数据

javascript - React 的 Virtual DOM 比 DOM 快多少?

c# - 消息奇偶校验

c++ - 使用 CppAD 时,IPOPT 不服从约束但不记录违规

algorithm - 稳定高效地求解大噪声多项式方程