线性代数-矩阵-【5】矩阵化简 C和C++实现

点击这里可以跳转至

【1】矩阵汇总:http://www.cnblogs.com/HongYi-Liang/p/7287369.html

【2】矩阵生成:http://www.cnblogs.com/HongYi-Liang/p/7275278.html

【3】矩阵加减:http://www.cnblogs.com/HongYi-Liang/p/7287403.html

【4】矩阵点乘:http://www.cnblogs.com/HongYi-Liang/p/7287324.html

【5】矩阵化简:现在的位置

(待续)

...


C++语言:

高斯消元法:

继续使用这个矩阵

当我们使用高斯消元(无回代)化简这个矩阵,是这样算的:

上述过程归纳为:

  1. 找到第一行行的主元(第一行第一个数:1)
  2. 消除第而三行的的第一个数(r2-2*r1;r3-4*r1)
  3. 找到第二行的主元(第二行第二个数:-2)
  4. 消除第三行的第二个数(r3-3/2*r2)

可以发现实际上是1和2两个步骤的循环,所以写成循环的形式

  • 从第一行开始到最后一行
  1. 找主元:找出第i的主元(第i行第i个数)
  2. 消元:消除下面所有行的第i个数(下面每一行减去x倍的第一行来消除第i列)

到目前为止,基本达到消元的目的了,但是有一些小小的瑕疵

我们可能碰到一个这样矩阵,有一行全是0,例如这个:

那么我们在步骤1中搜索到主元为0的话,0的任意倍数都是0,会导致第2步无法进行。所以我们需要添加换行的操作,计算方法为:

所以我们把代码逻辑修改成这样:

  • 从第一行开始到最后一行
  1. 找主元:找出第i的主元(第i行第i个数),若主元为0,把第i行向下换行,直到找到有主元的行。若找不到主元,就开始找下一个
  2. 消元:消除下面所有行的第i个数(下面每一行减去x倍的第一行来消除第i列)

下面就是高斯消元的主程序:

template <typename T>
bool Matrix<T>::GaussianElimination()
{
    Matrix<T> outputMatrix = *this;

    /*Gaussian elmiation*/
    for(int k=0;k<outputMatrix.m_iRows;k++)
    {
        /*if all the pivot have been found*/
        if(k>=m_iColumns)
        {
            break;
        }

        /*exchange rows downward to find the row‘s pivot*/
        for(int i=k+1;i<outputMatrix.m_iRows;i++)
        {
            /*pivot is non-zero*/
            if(outputMatrix.m_vecMatrix[k][k] != 0)
            {
                //T temp = outputMatrix.m_vecMatrix[0][0];
                break;
            }
            else
            {
                if(i < outputMatrix.m_iRows)
                {
                    outputMatrix.exchangeRows(k,i);
                }
            }
        }

        /*if there is no pivot in this row*/
        if(outputMatrix.m_vecMatrix[k][k] == 0)
        {
            break;
        }

        /*elimination:The rows below pivot row subtract times of pivot row*/
        for(int i=k+1;i<outputMatrix.m_iRows;i++)
        {
            double RowsfirstData = outputMatrix.m_vecMatrix[i][k]/outputMatrix.m_vecMatrix[k][k];//Save the first data of next(k+1) rows
            if(RowsfirstData != 0)
            {
                outputMatrix.m_vecMatrix[i][k]=0;
                for(int j=k+1;j<outputMatrix.m_iColumns;j++)
                {
                    outputMatrix.m_vecMatrix[i][j] -= RowsfirstData*outputMatrix.m_vecMatrix[k][j] ;
                }
            }
        }
    }

    *this = outputMatrix;
    return true;
}

高斯-若尔当法

若尔当在高斯消元的基础上加上了回代过程,把矩阵化简成行最简式。我们在高斯消元的基础上加上和回代,方法跟高斯消元相反,用上面的行减下面的行,这里就不详细描述(展开查看代码)

rref()//化简矩阵成行最简

template <typename T>
bool Matrix<T>::rref()
{
    Matrix<T> outputMatrix = *this;
    int rank=0;//the rank of the matrix, how many columns‘s pivot will it has(-1)

    /*Gaussian elmiation*/
    for(int k=0;k<outputMatrix.m_iRows;k++)
    {
        /*if all the pivot elem have been found*/
        if(k>=m_iColumns)
        {
            break;
        }

        /*exchange rows downward to find the pivot row*/
        for(int i=k+1;i<outputMatrix.m_iRows;i++)
        {
            /*pivot is non-zero*/
            if(outputMatrix.m_vecMatrix[k][k] != 0)
            {
                //T temp = outputMatrix.m_vecMatrix[0][0];
                rank++;
                break;
            }
            else
            {
                if(i < outputMatrix.m_iRows)
                {
                    outputMatrix.exchangeRows(k,i);
                }
            }
        }

        /*if there is no pivot in this row*/
        if(outputMatrix.m_vecMatrix[k][k] == 0)
        {
            break;
        }

        /*elimination:The rows below pivot row subtract times of pivot row*/
        for(int i=k+1;i<outputMatrix.m_iRows;i++)
        {
            double RowsfirstData = outputMatrix.m_vecMatrix[i][k]/outputMatrix.m_vecMatrix[k][k];//Save the first data of next(k+1) rows
            if(RowsfirstData != 0)
            {
                outputMatrix.m_vecMatrix[i][k]=0;
                for(int j=k+1;j<outputMatrix.m_iColumns;j++)
                {
                    outputMatrix.m_vecMatrix[i][j] -= RowsfirstData*outputMatrix.m_vecMatrix[k][j] ;
                }
            }
        }
    }

    /*normalizing:set all pivots to 1*/
    for(int i=0;i<outputMatrix.m_iRows;i++)
    {
        for(int j=0;j<outputMatrix.m_iColumns;j++)
        {
            if(outputMatrix.m_vecMatrix[i][j] !=0 )//pivot has been foound
            {
                double pivot = outputMatrix.m_vecMatrix[i][j];//get pivot
                for(int k=i;k<outputMatrix.m_iColumns;k++)
                {
                    outputMatrix.m_vecMatrix[i][k] /=pivot;
                }
                break;
            }
        }
    }

    /*Back substitution*/
    for(int i = rank;i>=1;i--)
    {
        /*find a first non-zero elem (It is pivot)*/
        for(int j=0;j<outputMatrix.m_iColumns;j++)
        {
            double times=0;
            if(outputMatrix.m_vecMatrix[i][j] !=0)//pivot found
            {
                for(int l=i-1;l>=0;l--)
                {
                    times = outputMatrix.m_vecMatrix[l][j]/outputMatrix.m_vecMatrix[i][j];
                    for(int k=j;k<outputMatrix.m_iColumns;k++)//tims of this row subtract by each columns in upon row
                    {
                        outputMatrix.m_vecMatrix[l][k] -= times*outputMatrix.m_vecMatrix[i][k];
                    }
                }
                break;
            }
        }
    }

    *this = outputMatrix;
    return true;
}

rrefmovie()//化简矩阵成行最简,并打印过程

template <typename T>
bool Matrix<T>::rrefmovie()
{
    Matrix<T> outputMatrix = *this;
    int rank=0;//the rank of the matrix, how many columns‘s pivot will it has(-1)

    /*Gauss elmiation*/
    cout<<"Gauss elimination:"<<endl;
    outputMatrix.printfAll();
    for(int k=0;k<outputMatrix.m_iRows;k++)
    {
        /*If all the pivot elem have been found*/
        if(k>=m_iColumns)
        {
            break;
        }

        /*Exchange rows downward to find the pivot row*/
        for(int i=k+1;i<outputMatrix.m_iRows;i++)
        {
            /*Pivot is non-zero*/
            if(outputMatrix.m_vecMatrix[k][k] != 0)
            {
                rank++;
                break;
            }
            else
            {
                if(i < outputMatrix.m_iRows)
                {
                    outputMatrix.exchangeRows(k,i);
                }
            }
            if(k!=i)
            {
                cout<<"row"<<k+1<<" exchange row"<<i+1<<endl;//Debug
                outputMatrix.printfAll();
            }
        }

        /*If there is no pivot in this row*/
        if(outputMatrix.m_vecMatrix[k][k] == 0)
        {
            break;
        }

        /*Elimination:The rows below pivot row subtract times of pivot row*/
        for(int i=k+1;i<outputMatrix.m_iRows;i++)
        {
            double RowsfirstData = outputMatrix.m_vecMatrix[i][k]/outputMatrix.m_vecMatrix[k][k];//Save the first data of next(k+1) rows
            if(RowsfirstData != 0)
            {
                outputMatrix.m_vecMatrix[i][k]=0;
                for(int j=k+1;j<outputMatrix.m_iColumns;j++)
                {
                    outputMatrix.m_vecMatrix[i][j] -= RowsfirstData*outputMatrix.m_vecMatrix[k][j] ;
                }
            }
            cout<<"row"<<i+1<<" - "<<RowsfirstData<<"*"<<"row"<<k+1<<endl;//Debug
            outputMatrix.printfAll();
        }
    }

    /*Normalizing:set all rows pivot to 1*/
    for(int i=0;i<outputMatrix.m_iRows;i++)
    {
        for(int j=0;j<outputMatrix.m_iColumns;j++)
        {
            if(outputMatrix.m_vecMatrix[i][j] !=0 )//pivot has been foound
            {
                double pivot = outputMatrix.m_vecMatrix[i][j];//get pivot
                for(int k=i;k<outputMatrix.m_iColumns;k++)
                {
                    outputMatrix.m_vecMatrix[i][k] /=pivot;
                }
                cout<<"row"<<i+1<<" / "<<pivot<<endl;//Debug
                outputMatrix.printfAll();//Debug
                break;
            }
        }
    }

    /*Back substitution*/
    cout<<"Back substitution:"<<endl;
    for(int i = rank;i>=1;i--)
    {
        /*find a first non-zero elem (It is pivot)*/
        for(int j=0;j<outputMatrix.m_iColumns;j++)
        {
            double times=0;
            if(outputMatrix.m_vecMatrix[i][j] !=0)//pivot found
            {
                for(int l=i-1;l>=0;l--)
                {
                    times = outputMatrix.m_vecMatrix[l][j]/outputMatrix.m_vecMatrix[i][j];
                    for(int k=j;k<outputMatrix.m_iColumns;k++)//tims of this row subtract by each columns in upon row
                    {
                        outputMatrix.m_vecMatrix[l][k] -= times*outputMatrix.m_vecMatrix[i][k];
                    }
                    cout<<"row"<<l+1<<" - "<<times<<"*"<<"row"<<i+1<<endl;
                    outputMatrix.printfAll();
                }
                break;
            }
        }
    }

    *this = outputMatrix;
    return true;
}

使用我们开始的矩阵测试:

    Matrix<double> matrix(3,3);
    matrix.setSpecifiedElem(0,0,1);
    matrix.setSpecifiedElem(0,1,2);
    matrix.setSpecifiedElem(0,2,3);
    matrix.setSpecifiedElem(1,0,2);
    matrix.setSpecifiedElem(1,1,2);
    matrix.setSpecifiedElem(1,2,2);
    matrix.setSpecifiedElem(2,0,4);
    matrix.setSpecifiedElem(2,1,5);
    matrix.setSpecifiedElem(2,2,6);
    matrix.printfAll();

    matrix.rrefmovie();
    matrix.printfAll();
    system("pause");

结果:

时间: 2024-10-12 22:30:24

线性代数-矩阵-【5】矩阵化简 C和C++实现的相关文章

HDU 4565 So Easy! 数学 + 矩阵 + 整体思路化简

http://acm.hdu.edu.cn/showproblem.php?pid=4565 首先知道里面那个东西,是肯定有小数的,就是说小数部分是约不走的,(因为b限定了不是一个完全平方数). 因为(a - 1)^2 < b < (a ^ 2),所以其不是完全平方数,假如是,那么设其为c,则有a - 1 < c < a,这是矛盾的 所以,向上取整这个步骤,是必不可少的了. 那么,我在它后面加上一个< 1的数,同时使得它们结合成为整数,那就相当于帮它取整了.根据二项式定理 (

[线性代数] 2、矩阵

 第二章.矩阵 §1 矩阵概念的引入    §2 矩阵的定义 §3 特殊的矩阵    §4 矩阵与线性变换 2.1.定义简记为: 2.2.特殊矩阵 行数与列数都等于 n 的矩阵,称为 n 阶方阵.可记作An只有一行的矩阵 A=(a1,a2,...,an)称为行矩阵(或行向量) .元素全是零的矩阵称为零距阵.可记作 O .形如的方阵称为对角阵.记作:特别的,方阵 称为单位阵.记作: 2.3.矩阵与线性变换 PS:线性变换与矩阵之间存在着一一对应关系. PS: 投影变换.旋转变换是在二维和高维运算中

线性代数——矩阵与矩阵乘法

在刚接触线性代数时,最先学到的是行列式,随之而来的就是矩阵.矩阵的出现过于突兀,当初学习时完全不清楚它的概念,更不要说还有矩阵乘法等各种奇怪的算术操作.于是从网上学习了各种矩阵概念,受益良多,在此总结一下学到的概念. 一.矩阵 矩阵最早来自于方程组的系数及常数所构成的方阵.——百度百科 如此看来,矩阵和行列式还是有联系的,矩阵最初可能就是用来表示行列式用的 方程组 改写成矩阵的形式 然而矩阵的作用不仅限于此,它有着线性变换的作用,我们将通过分析矩阵乘法来详加解释 二.矩阵乘法 提起矩阵乘法,我们

hdu 1588 Gauss Fibonacci(矩阵嵌矩阵)

题目大意: 求出斐波那契中的 第 k*i+b 项的和. 思路分析: 定义斐波那契数列的矩阵 f(n)为斐波那契第n项 F(n) = f(n+1) f(n) 那么可以知道矩阵 A = 1 1 1  0 使得 F(n) = A * F(n+1) 然后我们化简最后的答案 sum = F(b) +   F(K+b) +  F (2*k +b).... sum = F(b) +  A^k F(b)    +   A^2k F(b)..... sum = (E+A^k + A^2k.....)*F(b) 那

省选算法学习-矩阵与矩阵快速幂

0x00 引入 矩阵,顾名思义,就是由数构成的矩形阵列 比如这样的:$\begin{array}{l}\begin{bmatrix}2&3&4\0&7&13\c&\alpha&\sqrt5\end{bmatrix}\\end{array}$ 就是一个3*3的矩阵 矩阵在信息学乃至数学里面的用处都非常广泛,下面就来介绍下它的一些基本知识,以及常用的地方.本文同时还会介绍矩阵快速幂以及快速矩阵乘法. 0x01 何为矩阵 矩阵的定义 其实就是上面那样的啦.....

卡诺图简单逻辑化简与五变量卡诺图化简

一.格雷码编码规则 画卡诺图的时候需要先将所有变量可能以格雷码的形式排列在方格两侧,所有变量有2^n个,虽然我们常用的变量为四个及以下,可以熟记格雷码,但为了学习还是有必要了解格雷码的编码规则.格雷码的基本特点就是任意两个相邻的代码只有一位二进制数不同,这样在数字电路中变化时每次就只有一位发生变化,提高了电路的稳定性. 规则: 自然二进制数到格雷码: 保留二进制码的最高位作为格雷码的最高位,而次高位格雷码为二进制码的高位与次高位相异或,而格雷码其余各位与次高位的求法相类似. 格雷码到自然二进制数

逻辑函数的化简 【数字电路】

逻辑函数的化简 先补点各种门的 basic knowledge NAND 与非 NOR或非 XOR异或 XNOR 同或 对于同或,异或之前一直没搞明白....那个该死的标记老是混淆,也不知道为嘛标记的发明人为嘛要那么标记 ...现在知道了XOR...所以异或的标记是一个圈中间一把×             化简: 上面预设的ABCD的值输出结果是1 至于化简过程是为嘛...这个就是一步步化简....各种求并消项 切记!不要搞这种傻事! 然后就是另外一个很重要的化简方法--卡诺图 将n变量的全部最

HDU 5912 Fraction(模拟——分子式化简求解)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5912 Problem Description Mr. Frog recently studied how to add two fractions up, and he came up with an evil idea to trouble you by asking you to calculate the result of the formula below: As a talent, c

UVA - 10886 - Standard Deviation(化简 + 暴力)

题意:求如下函数产生的值的前 n 项的标准差(1 <= n <= 10000000,0 <= seed < 2^64). long double gen(){ static const long double Z = ( long double )1.0 / (1LL<<32); seed >>= 16; seed &= ( 1ULL << 32 ) - 1; seed *= seed; return seed * Z; } 写出方差的式