Gauss消去法(C++)

news2024/11/17 12:31:01

文章目录

  • 算法描述
    • 顺序Gauss消去法
    • 列选主元Gauss消去法
    • 全选主元Gauss消去法
    • Gauss-Jordan消去法
  • 算法实现
    • 顺序Gauss消去法
    • 列选主元Gauss消去法
    • 全选主元Gauss消去法
    • 列选主元Gauss-Jordan消去法
  • 实例分析

Gauss消去法是求解线性方程组较为有效的方法, 它主要包括两个操作, 即消元和回代. 所谓消元是指将线性方程组转化为与其同解的上三角方程组; 回代是指通过上三角方程组逐个解出方程组的未知数. Gauss消去法通常有顺序Gauss消去法, 列主元Gauss消去法, 全主元Gauss消去法及Gauss-Jordan消去法.

算法描述

顺序Gauss消去法

顺序Gauss消去法是最简单的Gauss消去法, 其基本步骤如下:

  1. 将线性方程组的增广矩阵通过行变换, 化简成一个上三角矩阵. 这可以通过交换两行位置或者用一个数乘某一行加到另一行上面来实现.
  2. 从增广矩阵的最后一行开始, 依次回代, 求出解向量. 回代过程中, 需要将从上方得到的解代入下方方程进行求解.

虽然Gauss消去法可以解决线性方程组的问题, 但是它没有稳定性保证. 如果主元素比较小, 舍入误差可能会累积增大, 从而导致解的误差较大.

算法可描述为伪代码如下:

用顺序Gauss消去法求解线性方程组:

{ x + 2 y + 3 z = 1 4 x + 5 y + 6 z = 1 7 x + 8 y = 1 \begin{cases} x+2y+3z=1\\4x+5y+6z=1\\7x+8y=1 \end{cases} x+2y+3z=14x+5y+6z=17x+8y=1

利用顺序Gauss消去法得到如下消元过程:

( 1.000000 2.000000 3.000000 1 4.000000 5.000000 6.000000 1 7.000000 8.000000 0.000000 1 ) → ( 1.000000 2.000000 3.000000 1 0.000000 − 3.000000 − 6.000000 − 3 0.000000 − 6.000000 − 21.000000 − 6 ) → ( 1.000000 2.000000 3.000000 1 0.000000 − 3.000000 − 6.000000 − 3 0.000000 0.000000 − 9.000000 0 ) → ( 1.000000 2.000000 0.000000 1 0.000000 − 3.000000 0.000000 − 3 0.000000 0.000000 1.000000 0 ) → ( 1.000000 0.000000 0.000000 − 1 0.000000 1.000000 0.000000 1 0.000000 0.000000 1.000000 0 ) → ( 1.000000 0.000000 0.000000 − 1 0.000000 1.000000 0.000000 1 0.000000 0.000000 1.000000 0 ) \begin{aligned} &\begin{pmatrix} 1.000000&2.000000&3.000000& 1 \\ 4.000000&5.000000&6.000000& 1 \\ 7.000000&8.000000&0.000000& 1 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 1.000000&2.000000&3.000000& 1 \\ 0.000000&-3.000000&-6.000000& -3 \\ 0.000000&-6.000000&-21.000000& -6 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 1.000000&2.000000&3.000000& 1 \\ 0.000000&-3.000000&-6.000000& -3 \\ 0.000000&0.000000&-9.000000& 0 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 1.000000&2.000000&0.000000& 1 \\ 0.000000&-3.000000&0.000000& -3 \\ 0.000000&0.000000&1.000000& 0 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 1.000000&0.000000&0.000000& -1 \\ 0.000000&1.000000&0.000000& 1 \\ 0.000000&0.000000&1.000000& 0 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 1.000000&0.000000&0.000000& -1 \\ 0.000000&1.000000&0.000000& 1 \\ 0.000000&0.000000&1.000000& 0 \\ \end{pmatrix} \end{aligned} 1.0000004.0000007.0000002.0000005.0000008.0000003.0000006.0000000.000000111 1.0000000.0000000.0000002.0000003.0000006.0000003.0000006.00000021.000000136 1.0000000.0000000.0000002.0000003.0000000.0000003.0000006.0000009.000000130 1.0000000.0000000.0000002.0000003.0000000.0000000.0000000.0000001.000000130 1.0000000.0000000.0000000.0000001.0000000.0000000.0000000.0000001.000000110 1.0000000.0000000.0000000.0000001.0000000.0000000.0000000.0000001.000000110

列选主元Gauss消去法

在顺序Gauss消去法中, 并没有选择主元的步骤, 而是按照方程组的顺序进行消元和回代. 这种方法在某些情况下可能会因为计算的顺序而产生数值不稳定性, 导致计算结果与精确解的误差较大. 而且顺序Gauss消去法要求系数矩阵的各阶顺序主子式非零, 而这并不是方程组有解的必要条件. 在列选主元的Gauss消去法中, 每一步计算之前都会增加选择主元的步骤. 这个步骤是为了提高数值稳定性, 避免在计算过程中出现除数为零的情况. 因此, 列选主元的Gauss消去法在计算精度上通常优于顺序高斯消去法. 除此之外, 列选主元Gauss消去法只需要系数矩阵的行列式非零就可以进行计算.

算法可描述为伪代码如下:

用列选主元Gauss消去法求解上例线性方程组.

利用列选主元Gauss消去法得到如下消元过程:

( 1.000000 2.000000 3.000000 1 4.000000 5.000000 6.000000 1 7.000000 8.000000 0.000000 1 ) → ( 7.000000 8.000000 0.000000 1 4.000000 5.000000 6.000000 1 1.000000 2.000000 3.000000 1 ) → ( 7.000000 8.000000 0.000000 1 0.000000 0.428571 6.000000 0.428571 0.000000 0.857143 3.000000 0.857143 ) → ( 7.000000 8.000000 0.000000 1 0.000000 0.857143 3.000000 0.857143 0.000000 0.428571 6.000000 0.428571 ) → ( 7.000000 8.000000 0.000000 1 0.000000 0.857143 3.000000 0.857143 0.000000 0.000000 4.500000 0 ) → ( 7.000000 8.000000 0.000000 1 0.000000 0.857143 0.000000 0.857143 0.000000 0.000000 1.000000 0 ) → ( 7.000000 0.000000 0.000000 − 7 0.000000 1.000000 0.000000 1 0.000000 0.000000 1.000000 0 ) → ( 1.000000 0.000000 0.000000 − 1 0.000000 1.000000 0.000000 1 0.000000 0.000000 1.000000 0 ) \begin{aligned} &\begin{pmatrix} 1.000000&2.000000&3.000000& 1 \\ 4.000000&5.000000&6.000000& 1 \\ 7.000000&8.000000&0.000000& 1 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 7.000000&8.000000&0.000000& 1 \\ 4.000000&5.000000&6.000000& 1 \\ 1.000000&2.000000&3.000000& 1 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 7.000000&8.000000&0.000000& 1 \\ 0.000000&0.428571&6.000000& 0.428571 \\ 0.000000&0.857143&3.000000& 0.857143 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 7.000000&8.000000&0.000000& 1 \\ 0.000000&0.857143&3.000000& 0.857143 \\ 0.000000&0.428571&6.000000& 0.428571 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 7.000000&8.000000&0.000000& 1 \\ 0.000000&0.857143&3.000000& 0.857143 \\ 0.000000&0.000000&4.500000& 0 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 7.000000&8.000000&0.000000& 1 \\ 0.000000&0.857143&0.000000& 0.857143 \\ 0.000000&0.000000&1.000000& 0 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 7.000000&0.000000&0.000000& -7 \\ 0.000000&1.000000&0.000000& 1 \\ 0.000000&0.000000&1.000000& 0 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 1.000000&0.000000&0.000000& -1 \\ 0.000000&1.000000&0.000000& 1 \\ 0.000000&0.000000&1.000000& 0 \\ \end{pmatrix} \end{aligned} 1.0000004.0000007.0000002.0000005.0000008.0000003.0000006.0000000.000000111 7.0000004.0000001.0000008.0000005.0000002.0000000.0000006.0000003.000000111 7.0000000.0000000.0000008.0000000.4285710.8571430.0000006.0000003.00000010.4285710.857143 7.0000000.0000000.0000008.0000000.8571430.4285710.0000003.0000006.00000010.8571430.428571 7.0000000.0000000.0000008.0000000.8571430.0000000.0000003.0000004.50000010.8571430 7.0000000.0000000.0000008.0000000.8571430.0000000.0000000.0000001.00000010.8571430 7.0000000.0000000.0000000.0000001.0000000.0000000.0000000.0000001.000000710 1.0000000.0000000.0000000.0000001.0000000.0000000.0000000.0000001.000000110

全选主元Gauss消去法

全选主元Gauss消去法是在列选主元Gauss消去法的基础上, 进一步扩大主元的搜索区间到整个矩阵, 精度更高, 但需要更多的计算量. 全选主元法选取了矩阵中最大值的元素作为主元, 并进行列变换. 这使得在回代过程中, 未知数的位置可能发生改变, 因此需要同时对未知量的顺序进行变换, 从而增加了计算量. 实际使用时, 完全主元素消去法比列主元素消去法运算量大得多, 全选主元的计算时间大约是列选主元的两倍.

算法可描述为伪代码如下:

用全选主元Gauss消去法求解上例线性方程组.

利用全选主元Gauss消去法得到如下消元过程:

( 1.000000 2.000000 3.000000 1 4.000000 5.000000 6.000000 1 7.000000 8.000000 0.000000 1 ) → ( 8.000000 7.000000 0.000000 1 5.000000 4.000000 6.000000 1 2.000000 1.000000 3.000000 1 ) → ( 8.000000 7.000000 0.000000 1 0.000000 − 0.375000 6.000000 0.375 0.000000 − 0.750000 3.000000 0.75 ) → ( 8.000000 0.000000 7.000000 1 0.000000 6.000000 − 0.375000 0.375 0.000000 3.000000 − 0.750000 0.75 ) → ( 8.000000 0.000000 7.000000 1 0.000000 6.000000 − 0.375000 0.375 0.000000 0.000000 − 0.562500 0.5625 ) → ( 8.000000 0.000000 0.000000 8 0.000000 6.000000 0.000000 0 0.000000 0.000000 1.000000 − 1 ) → ( 8.000000 0.000000 0.000000 8 0.000000 1.000000 0.000000 0 0.000000 0.000000 1.000000 − 1 ) → ( 1.000000 0.000000 0.000000 1 0.000000 1.000000 0.000000 0 0.000000 0.000000 1.000000 − 1 ) \begin{aligned} &\begin{pmatrix} 1.000000&2.000000&3.000000& 1 \\ 4.000000&5.000000&6.000000& 1 \\ 7.000000&8.000000&0.000000& 1 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 8.000000&7.000000&0.000000& 1 \\ 5.000000&4.000000&6.000000& 1 \\ 2.000000&1.000000&3.000000& 1 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 8.000000&7.000000&0.000000& 1 \\ 0.000000&-0.375000&6.000000& 0.375 \\ 0.000000&-0.750000&3.000000& 0.75 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 8.000000&0.000000&7.000000& 1 \\ 0.000000&6.000000&-0.375000& 0.375 \\ 0.000000&3.000000&-0.750000& 0.75 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 8.000000&0.000000&7.000000& 1 \\ 0.000000&6.000000&-0.375000& 0.375 \\ 0.000000&0.000000&-0.562500& 0.5625 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 8.000000&0.000000&0.000000& 8 \\ 0.000000&6.000000&0.000000& 0 \\ 0.000000&0.000000&1.000000& -1 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 8.000000&0.000000&0.000000& 8 \\ 0.000000&1.000000&0.000000& 0 \\ 0.000000&0.000000&1.000000& -1 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 1.000000&0.000000&0.000000& 1 \\ 0.000000&1.000000&0.000000& 0 \\ 0.000000&0.000000&1.000000& -1 \\ \end{pmatrix} \end{aligned} 1.0000004.0000007.0000002.0000005.0000008.0000003.0000006.0000000.000000111 8.0000005.0000002.0000007.0000004.0000001.0000000.0000006.0000003.000000111 8.0000000.0000000.0000007.0000000.3750000.7500000.0000006.0000003.00000010.3750.75 8.0000000.0000000.0000000.0000006.0000003.0000007.0000000.3750000.75000010.3750.75 8.0000000.0000000.0000000.0000006.0000000.0000007.0000000.3750000.56250010.3750.5625 8.0000000.0000000.0000000.0000006.0000000.0000000.0000000.0000001.000000801 8.0000000.0000000.0000000.0000001.0000000.0000000.0000000.0000001.000000801 1.0000000.0000000.0000000.0000001.0000000.0000000.0000000.0000001.000000101

Gauss-Jordan消去法

Gauss-Jordan消去法是高斯消元法的另一个版本, 其方法与高斯消元法相同. 唯一相异之处是该算法产生出来的矩阵是一个简化行梯阵式, 而不是高斯消元法中的行梯阵式. 相比起高斯消元法, Gauss-Jordan消去法的效率较低, 但可以把方程组的解用矩阵一次过表示出来.

Gauss-Jordan消去法也有顺序, 列选主元和全选主元3种消去方式. 由于列主元素消去法的舍入误差一般已较小, 所以在实际计算中多用列主元素消去法. 故算法实现一般采用列选主元Gauss-Jordan消去法.

算法可描述为伪代码如下:

用列选主元Gauss消去法求解上例线性方程组.

利用列选主元Gauss-Jordan消去法得到如下消元过程:

( 1.000000 2.000000 3.000000 1 4.000000 5.000000 6.000000 1 7.000000 8.000000 0.000000 1 ) → ( 7.000000 8.000000 0.000000 1 4.000000 5.000000 6.000000 1 1.000000 2.000000 3.000000 1 ) → ( 1.000000 1.142857 0.000000 0.142857 0.000000 0.428571 6.000000 0.428571 0.000000 0.857143 3.000000 0.857143 ) → ( 1.000000 1.142857 0.000000 0.142857 0.000000 0.857143 3.000000 0.857143 0.000000 0.428571 6.000000 0.428571 ) → ( 1.000000 0.000000 − 4.000000 − 1 0.000000 1.000000 3.500000 1 0.000000 0.000000 4.500000 0 ) → ( 1.000000 0.000000 0.000000 − 1 0.000000 1.000000 0.000000 1 0.000000 0.000000 1.000000 0 ) \begin{aligned} &\begin{pmatrix} 1.000000&2.000000&3.000000& 1 \\ 4.000000&5.000000&6.000000& 1 \\ 7.000000&8.000000&0.000000& 1 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 7.000000&8.000000&0.000000& 1 \\ 4.000000&5.000000&6.000000& 1 \\ 1.000000&2.000000&3.000000& 1 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 1.000000&1.142857&0.000000& 0.142857 \\ 0.000000&0.428571&6.000000& 0.428571 \\ 0.000000&0.857143&3.000000& 0.857143 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 1.000000&1.142857&0.000000& 0.142857 \\ 0.000000&0.857143&3.000000& 0.857143 \\ 0.000000&0.428571&6.000000& 0.428571 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 1.000000&0.000000&-4.000000& -1 \\ 0.000000&1.000000&3.500000& 1 \\ 0.000000&0.000000&4.500000& 0 \\ \end{pmatrix}\\\rightarrow& \begin{pmatrix} 1.000000&0.000000&0.000000& -1 \\ 0.000000&1.000000&0.000000& 1 \\ 0.000000&0.000000&1.000000& 0 \\ \end{pmatrix} \end{aligned} 1.0000004.0000007.0000002.0000005.0000008.0000003.0000006.0000000.000000111 7.0000004.0000001.0000008.0000005.0000002.0000000.0000006.0000003.000000111 1.0000000.0000000.0000001.1428570.4285710.8571430.0000006.0000003.0000000.1428570.4285710.857143 1.0000000.0000000.0000001.1428570.8571430.4285710.0000003.0000006.0000000.1428570.8571430.428571 1.0000000.0000000.0000000.0000001.0000000.0000004.0000003.5000004.500000110 1.0000000.0000000.0000000.0000001.0000000.0000000.0000000.0000001.000000110

算法实现

首先进行预处理如下:

#include <armadillo>
#include <vector>
using namespace arma;
using namespace std;

顺序Gauss消去法

/*
 * 顺序Gauss消去法
 * A : 系数矩阵
 * b : 常数向量
 * uA: 系数矩阵消元过程
 * ub: 常数向量消元过程
 * e : 判零标准
 *
 * 返回(bool):
 *  true : 求解失败
 *  false: 求解成功
 *
 * 不检查矩阵维数是否匹配问题
 */
bool Sequential_Gauss(mat A, vec b, vector<mat> &uA, vector<vec> &ub, const double &e = 1e-6)
{
    uA.clear();
    ub.clear();
    uA.push_back(A);
    ub.push_back(b);
    unsigned n(A.n_cols - 1), m(-1);
    // 消元
    for (unsigned i(0); i != n; ++i) // arma::mat的迭代器不太好用, 最后还是用了下标形式, 效率相比迭代器低一些
    {
        if (A.at(i, i) < e && A.at(i, i) > -e)
            return true;
        for (unsigned j(i + 1); j != A.n_cols; ++j)
        {
            double t(A.at(j, i) / A.at(i, i));
            A.at(j, i) = 0;
            b.at(j) -= t * b.at(i);
            for (unsigned k(i + 2); k < A.n_cols; ++k)
                A.at(j, k) -= t * A.at(i, k);
        }
        uA.push_back(A);
        ub.push_back(b);
    }
    // 回代
    do
    {
        if (A.at(n, n) < e && A.at(n, n) > -e)
            return true;
        b.at(n) /= A.at(n, n);
        A.at(n, n) = 1;
        for (unsigned i(0); i != n; ++i)
        {
            b.at(i) -= A.at(i, n) * b.at(n);
            A.at(i, n) = 0;
        }
        uA.push_back(A);
        ub.push_back(b);
    } while (--n != m);
    return false;
}

列选主元Gauss消去法

/*
 * 列选主元Gauss消去法
 * A : 系数矩阵
 * b : 常数向量
 * uA: 系数矩阵消元过程
 * ub: 常数向量消元过程
 * e : 判零标准
 *
 * 返回(bool):
 *  true : 求解失败
 *  false: 求解成功
 *
 * 不检查矩阵维数是否匹配问题
 */
bool Col_Gauss(mat A, vec b, vector<mat> &uA, vector<vec> &ub, const double &e = 1e-6)
{
    uA.clear();
    ub.clear();
    uA.push_back(A);
    ub.push_back(b);
    unsigned n(A.n_cols - 1), m(-1);
    for (unsigned i(0); i != n; ++i) // 消元
    {
        unsigned max(i); // 选列主元
        for (unsigned j(i + 1); j != A.n_cols; ++j)
            if (abs(A.at(j, i)) > abs(A.at(max, i)))
                max = j;
        if (abs(A.at(max, i)) < e)
            return true;
        if (max != i)
        {
            for (unsigned j(i); j != A.n_cols; ++j)
            {
                double t(A.at(i, j));
                A.at(i, j) = A.at(max, j);
                A.at(max, j) = t;
            }
            double t(b.at(max));
            b.at(max) = b.at(i);
            b.at(i) = t;
            uA.push_back(A);
            ub.push_back(b);
        }
        for (unsigned j(i + 1); j != A.n_cols; ++j)
        {
            double t(A.at(j, i) / A.at(i, i));
            A.at(j, i) = 0;
            b.at(j) -= t * b.at(i);
            for (unsigned k(i + 1); k < A.n_cols; ++k)
                A.at(j, k) -= t * A.at(i, k);
        }
        uA.push_back(A);
        ub.push_back(b);
    }
    do // 回代
    {
        if (A.at(n, n) < e && A.at(n, n) > -e)
            return true;
        b.at(n) /= A.at(n, n);
        A.at(n, n) = 1;
        for (unsigned i(0); i != n; ++i)
        {
            b.at(i) -= A.at(i, n) * b.at(n);
            A.at(i, n) = 0;
        }
        uA.push_back(A);
        ub.push_back(b);
    } while (--n != m);
    return false;
}

全选主元Gauss消去法

/*
 * 全选主元Gauss消去法
 * A : 系数矩阵
 * b : 常数向量
 * uA: 系数矩阵消元过程
 * ub: 常数向量消元过程
 * r : 解向量
 * e : 判零标准
 *
 * 返回(bool):
 *  true : 求解失败
 *  false: 求解成功
 *
 * 不检查矩阵维数是否匹配问题
 */
bool All_Gauss(mat A, vec b, vector<mat> &uA, vector<vec> &ub, vec &r, const double &e = 1e-6)
{
    uA.clear();
    ub.clear();
    uA.push_back(A);
    ub.push_back(b);
    r.zeros(A.n_cols);
    unsigned n(A.n_cols - 1), m(-1), *a(new unsigned[A.n_cols]);
    for (unsigned t(0); t < A.n_rows; ++t) // 初始化排序向量
        a[t] = t;
    for (unsigned i(0); i != n; ++i) // 消元
    {
        unsigned x(i), y(i); // 选主元
        for (unsigned j(i); j != A.n_cols; ++j)
            for (unsigned k(i); k != A.n_cols; ++k)
                if (abs(A.at(j, k)) > abs(A.at(x, y)))
                {
                    x = j;
                    y = k;
                }
        if (abs(A.at(x, y)) < e)
        {
            delete[] a;
            return true;
        }
        bool flag(false);
        if (x != i)
        {
            for (unsigned j(i); j < A.n_cols; ++j)
            {
                double t(A.at(x, j));
                A.at(x, j) = A.at(i, j);
                A.at(i, j) = t;
            }
            double t(b.at(x));
            b.at(x) = b.at(i);
            b.at(i) = t;
            flag = true;
        }
        if (y != i)
        {
            for (unsigned j(0); j < A.n_cols; ++j)
            {
                double t(A.at(j, i));
                A.at(j, i) = A.at(j, y);
                A.at(j, y) = t;
            }
            flag = true;
            unsigned t(a[i]);
            a[i] = a[y];
            a[y] = t;
        }
        if (flag)
        {
            uA.push_back(A);
            ub.push_back(b);
        }
        for (unsigned j(i + 1); j != A.n_cols; ++j)
        {
            double t(A.at(j, i) / A.at(i, i));
            A.at(j, i) = 0;
            b.at(j) -= t * b.at(i);
            for (unsigned k(i + 2); k < A.n_cols; ++k)
                A.at(j, k) -= t * A.at(i, k);
        }
        uA.push_back(A);
        ub.push_back(b);
    }
    do // 回代
    {
        if (abs(A.at(n, n)) < e)
        {
            delete[] a;
            return true;
        }
        r.at(a[n]) = b.at(n) /= A.at(n, n);
        A.at(n, n) = 1;
        for (unsigned i(0); i != n; ++i)
        {
            b.at(i) -= A.at(i, n) * b.at(n);
            A.at(i, n) = 0;
        }
        uA.push_back(A);
        ub.push_back(b);
    } while (--n != m);
    delete[] a;
    return false;
}

列选主元Gauss-Jordan消去法

/*
 * 列选主元Gauss-Jordan消去法
 * A : 系数矩阵
 * b : 常数向量
 * uA: 系数矩阵消元过程
 * ub: 常数向量消元过程
 * e : 判零标准
 *
 * 返回(bool):
 *  true : 求解失败
 *  false: 求解成功
 *
 * 不检查矩阵维数是否匹配问题
 */
bool Gauss_Jordan(mat A, vec b, vector<mat> &uA, vector<vec> &ub, const double &e = 1e-6)
{
    uA.clear();
    ub.clear();
    uA.push_back(A);
    ub.push_back(b);
    unsigned n(A.n_cols - 1);
    for (unsigned i(0); i != n; ++i)
    {
        unsigned max(i); // 选列主元
        for (unsigned j(i + 1); j != A.n_cols; ++j)
            if (abs(A.at(j, i)) > abs(A.at(max, i)))
                max = j;
        if (abs(A.at(max, i)) < e)
            return true;
        if (max != i)
        {
            for (unsigned j(i); j != A.n_cols; ++j)
            {
                double t(A.at(i, j));
                A.at(i, j) = A.at(max, j);
                A.at(max, j) = t;
            }
            double t(b.at(max));
            b.at(max) = b.at(i);
            b.at(i) = t;
            uA.push_back(A);
            ub.push_back(b);
        }
        b.at(i) /= A.at(i, i);
        for (unsigned k(i + 1); k != A.n_cols; ++k)
            A.at(i, k) /= A.at(i, i);
        for (unsigned j(i + 1); j < A.n_rows; ++j)
        {
            b.at(j) -= b.at(i) * A.at(j, i);
            for (unsigned k(i + 1); k < A.n_cols; ++k)
                A.at(j, k) -= A.at(i, k) * A.at(j, i);
            A.at(j, i) = 0;
        }
        for (unsigned j(0); j != i; ++j)
        {
            b.at(j) -= b.at(i) * A.at(j, i);
            for (unsigned k(i + 1); k < A.n_cols; ++k)
                A.at(j, k) -= A.at(i, k) * A.at(j, i);
            A.at(j, i) = 0;
        }
        A.at(i, i) = 1;
        uA.push_back(A);
        ub.push_back(b);
    }
    return false;
}

实例分析

用列主元高斯消去法求解方程组

{ 0.101 x 1 + 2.304 x 2 + 3.555 x 3 = 1.183 − 1.347 x 1 + 3.712 x 2 + 4.623 x 3 = 2.137 − 2.835 x 1 + 1.072 x 2 + 5.643 x 3 = 3.035 \begin{cases} 0.101x_1+2.304x_2+3.555x_3=1.183\\ -1.347x_1+3.712x_2+4.623x_3=2.137\\ -2.835x_1+1.072x_2+5.643x_3=3.035 \end{cases} 0.101x1+2.304x2+3.555x3=1.1831.347x1+3.712x2+4.623x3=2.1372.835x1+1.072x2+5.643x3=3.035

代入程序, 求得列主元高斯消元过程如下:

( 0.101000 2.304000 3.555000 1.183 − 1.347000 3.712000 4.623000 2.137 − 2.835000 1.072000 5.643000 3.035 ) → ( − 2.835000 1.072000 5.643000 3.035 − 1.347000 3.712000 4.623000 2.137 0.101000 2.304000 3.555000 1.183 ) → ( − 2.835000 1.072000 5.643000 3.035 0.000000 3.202658 1.941829 0.694974 0.000000 2.342191 3.756038 1.29113 ) → ( − 2.835000 1.072000 5.643000 3.035 0.000000 3.202658 1.941829 0.694974 0.000000 0.000000 2.335926 0.782872 ) → ( − 2.835000 1.072000 0.000000 1.14378 0.000000 3.202658 0.000000 0.0441809 0.000000 0.000000 1.000000 0.335144 ) → ( − 2.835000 0.000000 0.000000 1.12899 0.000000 1.000000 0.000000 0.0137951 0.000000 0.000000 1.000000 0.335144 ) → ( 1.000000 0.000000 0.000000 − 0.398234 0.000000 1.000000 0.000000 0.0137951 0.000000 0.000000 1.000000 0.335144 ) \begin{aligned} \begin{pmatrix} 0.101000&2.304000&3.555000& 1.183 \\ -1.347000&3.712000&4.623000& 2.137 \\ -2.835000&1.072000&5.643000& 3.035 \\ \end{pmatrix}\\\rightarrow \begin{pmatrix} -2.835000&1.072000&5.643000& 3.035 \\ -1.347000&3.712000&4.623000& 2.137 \\ 0.101000&2.304000&3.555000& 1.183 \\ \end{pmatrix}\\\rightarrow \begin{pmatrix} -2.835000&1.072000&5.643000& 3.035 \\ 0.000000&3.202658&1.941829& 0.694974 \\ 0.000000&2.342191&3.756038& 1.29113 \\ \end{pmatrix}\\\rightarrow \begin{pmatrix} -2.835000&1.072000&5.643000& 3.035 \\ 0.000000&3.202658&1.941829& 0.694974 \\ 0.000000&0.000000&2.335926& 0.782872 \\ \end{pmatrix}\\\rightarrow \begin{pmatrix} -2.835000&1.072000&0.000000& 1.14378 \\ 0.000000&3.202658&0.000000& 0.0441809 \\ 0.000000&0.000000&1.000000& 0.335144 \\ \end{pmatrix}\\\rightarrow \begin{pmatrix} -2.835000&0.000000&0.000000& 1.12899 \\ 0.000000&1.000000&0.000000& 0.0137951 \\ 0.000000&0.000000&1.000000& 0.335144 \\ \end{pmatrix}\\\rightarrow \begin{pmatrix} 1.000000&0.000000&0.000000& -0.398234 \\ 0.000000&1.000000&0.000000& 0.0137951 \\ 0.000000&0.000000&1.000000& 0.335144 \\ \end{pmatrix} \end{aligned} 0.1010001.3470002.8350002.3040003.7120001.0720003.5550004.6230005.6430001.1832.1373.035 2.8350001.3470000.1010001.0720003.7120002.3040005.6430004.6230003.5550003.0352.1371.183 2.8350000.0000000.0000001.0720003.2026582.3421915.6430001.9418293.7560383.0350.6949741.29113 2.8350000.0000000.0000001.0720003.2026580.0000005.6430001.9418292.3359263.0350.6949740.782872 2.8350000.0000000.0000001.0720003.2026580.0000000.0000000.0000001.0000001.143780.04418090.335144 2.8350000.0000000.0000000.0000001.0000000.0000000.0000000.0000001.0000001.128990.01379510.335144 1.0000000.0000000.0000000.0000001.0000000.0000000.0000000.0000001.0000000.3982340.01379510.335144

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1379070.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TypeScript学习笔记、鸿蒙开发学习笔记

变量定义方式 # 变量声明 let msg: string douzi console.log(msg) let num: number 20 console.log(num) let end: boolean true console.log("end" end) let a: any 10 a douzi console.log(a) let p {name:"douzi",age:20} console.log(p.name)…

30天精通Nodejs--第十七天:express-路由配置

目录 引言基础路由配置路由参数与查询参数路由前缀与子路由路由重定向结语 引言 上篇文章我们简单介绍了express的基础用法&#xff0c;包括express的安装、创建路由及项目启动&#xff0c;对express有了一个基础的了解&#xff0c;这篇开始我们将详细介绍express的一些高级用…

docker安装nacos+mysql+配置网络

一、配置网络 为什么要配置网络&#xff1f;因为 Nacos 内要连接MySQL数据库的&#xff0c;我的 MySQL 数据库也是用 Docker启动的&#xff0c;所以2个容器间要通信是需要配置他们使用相同的网络。这个操作要在启动Nacos容器之前。 注意&#xff1a;这里配置的网络只在镜像内部…

聚对苯二甲酸乙二醇酯PET的特性有哪些?UV胶水能够粘接聚对苯二甲酸乙二醇酯PET吗?又有哪些优势呢?

聚对苯二甲酸乙二醇酯&#xff08;Polyethylene Terephthalate&#xff0c;PET&#xff09;是一种常见的塑料材料&#xff0c;具有许多特性&#xff0c;包括&#xff1a; 1.化学式&#xff1a; PET的化学式为 (C10H8O4)n&#xff0c;其中n表示重复单元的数量。 2.透明度&#…

掌握 gRPC 和 RPC 的关键区别

一、远程过程调用协议简介 1、RPC 的本质 首先&#xff0c;我们探讨一下什么是 RPC。RPC&#xff0c;缩写为 Remote Procedure Call Protocol&#xff0c;直译来看就是远程过程调用协议。 讲得通俗一些&#xff1a; RPC 是一种通信机制RPC 实现了客户端/服务器通信模型 官…

【大厂秘籍】 - Redis持久化篇

创作不易&#xff0c;你的关注分享就是博主更新的最大动力&#xff0c; 每周持续更新 微信搜索【 企鹅君】关注还能领取学习资料喔&#xff0c;第一时间阅读(比博客早两到三篇) 求关注❤️ 求点赞❤️ 求分享❤️ 对博主真的非常重要 企鹅君原创&#xff5c;GitHub开源项目gith…

【算法】信使(最短路问题)

题目 战争时期&#xff0c;前线有 n 个哨所&#xff0c;每个哨所可能会与其他若干个哨所之间有通信联系。 信使负责在哨所之间传递信息&#xff0c;当然&#xff0c;这是要花费一定时间的&#xff08;以天为单位&#xff09;。 指挥部设在第一个哨所。 当指挥部下达一个命令…

<软考高项备考>《论文专题 - 63 质量管理(2) 》

2 过程1-规划质量管理 2.1 问题 4W1H过程做什么识别项目及其可交付成果的质量要求、标准&#xff0c;并书面描述项目将如何证明符合质量要求、标准的过程&#xff1b;作用&#xff1a;为在整个项目期间如何管理和核实质量提供指南和方向为什么做1、识别项目/产品质量要求和标…

debian 11 arm64 aarch64 D2000 平台编译 box86 box64 笔记

参考资料 https://github.com/ptitSeb/box86/blob/master/docs/COMPILE.md 源码地址 GitHub - ptitSeb/box86: Box86 - Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices deb在线源地址&#xff08;打不开&#xff09;&#xff1a; Itais box86…

两个阅读英文论文的免费AI工具

大家好啊&#xff0c;我是董董灿。 本文会介绍我平时用到的两个免费的基于GPT的论文阅读平台&#xff0c;很好用&#xff0c;对于有英文阅读困难症的小伙伴(比如我)是真的提效。 1、 英文阅读困难症 在我的工作以及业余学习中&#xff0c;会时不时的需要翻看一些英文论文&…

GitLab任意用户密码重置漏洞(CVE-2023-7028)

GitLab CVE-2023-7028 POC user[email][]validemail.com&user[email][]attackeremail.com 本文链接&#xff1a; https://www.黑客.wang/wen/47.html

JavaScript保留字和预定义的全局变量及函数汇总

保留字也称关键字&#xff0c;每种语言中都有该语言本身规定的一些关键字&#xff0c;这些关键字都是该语言的语法实现基础&#xff0c;JavaScript中规定了一些标识符作为现行版本的关键字或者将来版本中可能会用到的关键字&#xff0c;所以当我们定义标识符时就不能使用这些关…

【Git】本地仓库文件的创建、修改和删除

目录 一、基本信息设置 1、设置用户名2、设置用户名邮箱 二、Git仓库操作介绍 1、创建一个新的文件夹2、在文件内初始化git仓库&#xff08;创建git仓库&#xff09;3、向仓库中添加文件 1.创建一个文件2.将文件添加到暂存区3.将暂存区添加到仓库 4、修改仓库文件 1.修改文件2.…

汽车级线性电压稳压器LM317MBSTT3G:新能源汽车的理想之选

LM317MBSTT3G是一款可调三端子正向线性稳压器&#xff0c;能够在 1.2 V 至 37 V 的输出电压范围内提供 500 mA 以上的电流。此线性电压稳压器使用非常简便&#xff0c;仅需两个外部电阻即可设置输出电压。另外&#xff0c;它采用内部电流限制、高温关断和安全区域补偿&#xff…

边缘计算:连接实时数据的力量与未来发展之路

边缘计算是一种分布式计算范式&#xff0c;它旨在将数据处理、存储和应用服务带到数据源的近端&#xff0c;即网络的“边缘”。在边缘计算模型中&#xff0c;算力和存储资源距离末端用户或数据源更近&#xff0c;这减少了数据在网络中传输的距离&#xff0c;从而降低延迟&#…

【Web】token机制

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Web ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 机制基本&#xff1a; 优势&#xff1a; 结语 我的其他博客 前言 在当今互联网时代&#xff0c;安全、高效的用户身份验证和资源授…

关于Python里xlwings库对Excel表格的操作(三十二)

这篇小笔记主要记录如何【如何使用“Chart类”、“Api类"和“Axes函数”设置坐标轴标题文本内容】。 前面的小笔记已整理成目录&#xff0c;可点链接去目录寻找所需更方便。 【目录部分内容如下】【点击此处可进入目录】 &#xff08;1&#xff09;如何安装导入xlwings库…

Sip - Ubuntu 配置 miniSIPServer 服务器(测试用)

客户提供的账号过期了&#xff0c;简单搭建 SIP 服务器&#xff0c;以便测试使用。个人认为这个配置起来最为简单&#xff0c;且测试功能足够。 官网miniSIPServer - 基于 Windows 以及 Linux 平台的 VoIP (SIP) 服务器软件. miniSIPServer 可能是最容易使用的 VoIP(SIP) 服务器…

【国产mcu填坑篇】华大单片机(小华半导体)一、SPI的DMA应用(发送主机)HC32L136

最近需要用华大的hc32l136的硬件SPIDMA传输&#xff0c;瞎写很久没调好&#xff0c;看参考手册&#xff0c;瞎碰一天搞通了。。。 先说下我之前犯的错误&#xff0c;也是最宝贵的经验&#xff0c;供参考 没多看参考手册直接写&#xff08;即使有点烂仍然提供了最高的参考价值。…

基于STM32和ESP8266的物联网应用开发与实现

基于STM32和ESP8266的物联网应用开发与实现可以实现智能家居、智能工业、环境监测等多种应用&#xff0c;它将结合STM32微控制器的实时控制能力和ESP8266无线通信模块的WiFi连接能力。在本文中&#xff0c;我们将介绍如何设计和实现这样的物联网应用&#xff0c;并提供相关的代…