关键词

JS求解三元一次方程组值的方法

JS求解三元一次方程组值的方法

解三元一次方程组即为求解下列形式的方程:

a1*x + b1*y + c1*z = d1
a2*x + b2*y + c2*z = d2
a3*x + b3*y + c3*z = d3

其中,x、y、z分别为未知数,其他为已知数(系数和常数)。解方程的过程就是求出未知数x、y、z的值。

利用矩阵求解

其中,最通用的 method 是利用矩阵逆推法,将方程组写成矩阵的形式,然后进行高斯-约旦(高斯消元法)消元,进而解出待定量。

function calcEquation(mat, val) {
  const eps = 1e-10, n = mat.length;
  const a = Array(n).fill(0).map(() => Array(n + 1).fill(0));
  for (let i = 0; i < n; ++i) {
    for (let j = 0; j < n; ++j) {
      a[i][j] = mat[i][j];
    }
    a[i][n] = val[i];
  }
  for (let i = 0; i < n; ++i) {
    let pivot = i;
    for (let j = i + 1; j < n; ++j) {
      if (Math.abs(a[j][i]) > Math.abs(a[pivot][i])) {
        pivot = j;
      }
    }
    [a[i], a[pivot]] = [a[pivot], a[i]];
    if (Math.abs(a[i][i]) < eps) {
      return null;
    }
    for (let j = i + 1; j < n; ++j) {
      const f = a[j][i] / a[i][i];
      for (let k = i + 1; k <= n; ++k) {
        a[j][k] -= f * a[i][k];
      }
    }
  }
  const x = Array(n).fill(0);
  for (let i = n - 1; i >= 0; --i) {
    for (let j = i + 1; j < n; ++j) {
      a[i][n] -= a[i][j] * x[j];
    }
    if (Math.abs(a[i][i]) < eps) {
      return null;
    }
    x[i] = a[i][n] / a[i][i];
  }
  return x;
}

案例示例

例如,我们要求解下列三元一次方程组:

3*x + 6*y - 2*z = 1
7*x - 5*y + 3*z = 2
4*y + 1*z = 5

首先将方程组转化为矩阵的形式:

3, 6, -2, 1
7, -5, 3, 2
0, 4, 1, 5

然后使用前面的函数进行计算:

calcEquation([[3, 6, -2], [7, -5, 3], [0, 4, 1]],
             [1, 2, 5]);

得到结果:

[0.5, 1, 2]

即x=0.5,y=1,z=2。另外,如果方程组无解,则会返回null。

更多矩阵逆推算法可以自行了解。

利用高斯约旦法求解

高斯约旦法是一种常用的解线性方程组的方法,它的基本思想是把线性方程组写成增广矩阵的形式,然后进行多次行变换,直到把增广矩阵化为行阶梯形矩阵,再进行回带求解过程,最终得到方程组的解。

function gauss(mat, val) {
  const n = mat.length;
  for (let i = 0; i < n; ++i) {
    let pivot = -1;
    for (let k = i; k < n; ++k) {
      if (Math.abs(mat[k][i]) > 0) {
        pivot = k;
        break;
      }
    }
    if (pivot === -1) {
      return null;
    }
    if (pivot !== i) {
      [mat[i], mat[pivot]] = [mat[pivot], mat[i]];
      [val[i], val[pivot]] = [val[pivot], val[i]];
    }
    const coeff = mat[i][i];
    for (let k = i + 1; k <= n; ++k) {
      mat[i][k] /= coeff;
    }
    val[i] /= coeff;
    for (let j = 0; j < n; ++j) {
      if (i === j) {
        continue;
      }
      const coefj = mat[j][i];
      for (let k = i + 1; k <= n; ++k) {
        mat[j][k] -= coefj * mat[i][k];
      }
      val[j] -= coefj * val[i];
    }
  }
  return val;
}

案例示例

例如,我们仍然要求解下列三元一次方程组:

3*x + 6*y - 2*z = 1
7*x - 5*y + 3*z = 2
4*y + 1*z = 5

将该方程组表示为增广矩阵的形式:

3, 6, -2, 1
7, -5, 3, 2
0, 4, 1, 5

然后使用高斯约旦法函数进行计算:

gauss([[3, 6, -2, 1], [7, -5, 3, 2], [0, 4, 1, 5]]);

得到结果:

[0.5, 1, 2]

即x=0.5,y=1,z=2。另外,如果方程组无解,则会返回null。

高斯约旦法的优点是简单易懂,实现起来比较容易。它的缺点是矩阵元素需要进行浮点运算,并且如果矩阵行列式为0,就不能使用该方法求解。

本文链接:http://task.lmcjl.com/news/11076.html

展开阅读全文