解三元一次方程组即为求解下列形式的方程:
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