C++矩阵运算类(Matrix.h)

2023-10-30

这个类数据类型是double,包含了常用的矩阵计算,多数方法经过实践验证,也难免有不足之处,如有发现欢迎指出。

https://github.com/ims0/comTutor/tree/master/matrix

#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <cmath>
using namespace std;
#ifndef _In_opt_
  #define _In_opt_
#endif
#ifndef _Out_
  #define _Out_
#endif


typedef unsigned Index_T;
class Matrix
{
private:
    Index_T m_row, m_col;
    Index_T m_size;
    Index_T m_curIndex;
    double *m_ptr;//数组指针
public:
    Matrix(Index_T r, Index_T c) :m_row(r), m_col(c)//非方阵构造
    {
        m_size = r*c;
        if (m_size>0)
        {
            m_ptr = new double[m_size];
        }
        else
            m_ptr = NULL;
    };
    Matrix(Index_T r, Index_T c, double val ) :m_row(r), m_col(c)// 赋初值val
    {
        m_size = r*c;
        if (m_size>0)
        {
            m_ptr = new double[m_size];
        }
        else
            m_ptr = NULL;
    };
    Matrix(Index_T n) :m_row(n), m_col(n)//方阵构造
    {
        m_size = n*n;
        if (m_size>0)
        {
            m_ptr = new double[m_size];
        }
        else
            m_ptr = NULL;
    };
    Matrix(const Matrix &rhs)//拷贝构造
    {
        m_row = rhs.m_row;
        m_col = rhs.m_col;
        m_size = rhs.m_size;
        m_ptr = new double[m_size];
        for (Index_T i = 0; i<m_size; i++)
            m_ptr[i] = rhs.m_ptr[i];
    }

    ~Matrix()
    {
        if (m_ptr != NULL)
        {
            delete[]m_ptr;
            m_ptr = NULL;
        }
    }

    Matrix  &operator=(const Matrix&);  //如果类成员有指针必须重写赋值运算符,必须是成员
    friend istream &operator>>(istream&, Matrix&);

    friend ofstream &operator<<(ofstream &out, Matrix &obj);  // 输出到文件
    friend ostream &operator<<(ostream&, Matrix&);          // 输出到屏幕
    friend Matrix &operator<<(Matrix &mat, const double val);
    friend Matrix& operator,(Matrix &obj, const double val);
    friend Matrix  operator+(const Matrix&, const Matrix&);
    friend Matrix  operator-(const Matrix&, const Matrix&);
    friend Matrix  operator*(const Matrix&, const Matrix&);  //矩阵乘法
    friend Matrix  operator*(double, const Matrix&);  //矩阵乘法
    friend Matrix  operator*(const Matrix&, double);  //矩阵乘法

    friend Matrix  operator/(const Matrix&, double);  //矩阵 除以单数

    Matrix multi(const Matrix&); // 对应元素相乘
    Matrix mtanh(); // 对应元素相乘
    Index_T row()const{ return m_row; }
    Index_T col()const{ return m_col; }
    Matrix getrow(Index_T index); // 返回第index 行,索引从0 算起
    Matrix getcol(Index_T index); // 返回第index 列

    Matrix cov(_In_opt_ bool flag = true);   //协方差阵 或者样本方差
    double det();   //行列式
    Matrix solveAb(Matrix &obj);  // b是行向量或者列向量
    Matrix diag();  //返回对角线元素
    //Matrix asigndiag();  //对角线元素
    Matrix T()const;   //转置
    void sort(bool);//true为从小到大
    Matrix adjoint();
    Matrix inverse();
    void QR(_Out_ Matrix&, _Out_ Matrix&)const;
    Matrix eig_val(_In_opt_ Index_T _iters = 1000);
    Matrix eig_vect(_In_opt_ Index_T _iters = 1000);

    double norm1();//1范数
    double norm2();//2范数
    double mean();// 矩阵均值
    double*operator[](Index_T i){ return m_ptr + i*m_col; }//注意this加括号, (*this)[i][j]
    void zeromean(_In_opt_  bool flag = true);//默认参数为true计算列
    void normalize(_In_opt_  bool flag = true);//默认参数为true计算列
    Matrix exponent(double x);//每个元素x次幂
    Matrix  eye();//对角阵
    void  maxlimit(double max,double set=0);//对角阵
};

/*
类方法的实现
*/

Matrix Matrix::mtanh() // 对应元素 tanh()
{
    Matrix ret(m_row, m_col);
    for (Index_T i = 0; i<ret.m_size; i++)
    {
        ret.m_ptr[i] = tanh(m_ptr[i]);
    }
    return ret;
}
/*
 * 递归调用
 */
double calcDet(Index_T n, double *&aa)
{
    if (n == 1)
        return aa[0];
    double *bb = new double[(n - 1)*(n - 1)];//创建n-1阶的代数余子式阵bb
    double sum = 0.0;
    for (Index_T Ai = 0; Ai<n; Ai++)
    {
        for (Index_T Bi = 0; Bi < n - 1; Bi++)//把aa阵第一列各元素的代数余子式存到bb
        {
            Index_T offset =  Bi < Ai ? 0 : 1; //bb中小于Ai的行,同行赋值,等于的错过,大于的加一
            for (Index_T j = 0; j<n - 1; j++)
            {
                bb[Bi*(n - 1) + j] = aa[(Bi + offset)*n + j + 1];
            }
        }
        int flag = (Ai % 2 == 0 ? 1 : -1);//因为列数为0,所以行数是偶数时候,代数余子式为1.
        sum += flag* aa[Ai*n] * calcDet(n - 1, bb);//aa第一列各元素与其代数余子式积的和即为行列式
    }
    delete[]bb;
    return sum;
}

Matrix Matrix::solveAb(Matrix &obj)
{
    Matrix ret(m_row, 1);
    if (m_size == 0 || obj.m_size == 0)
    {
        cout << "solveAb(Matrix &obj):this or obj is null" << endl;
        return ret;
    }
    if (m_row != obj.m_size)
    {
        cout << "solveAb(Matrix &obj):the row of two matrix is not equal!" << endl;
        return ret;
    }

    double *Dx = new double[m_row*m_row];
    for (Index_T i = 0; i<m_row; i++)
    {
        for (Index_T j = 0; j<m_row; j++)
        {
            Dx[i*m_row + j] = m_ptr[i*m_row + j];
        }
    }
    double D = calcDet(m_row, Dx);
    if (D == 0)
    {
        cout << "Cramer法则只能计算系数矩阵为满秩的矩阵" << endl;
        return  ret;
    }

    for (Index_T j = 0; j<m_row; j++)
    {
        for (Index_T i = 0; i<m_row; i++)
        {
            for (Index_T j = 0; j<m_row; j++)
            {
                Dx[i*m_row + j] = m_ptr[i*m_row + j];
            }
        }
        for (Index_T i = 0; i<m_row; i++)
        {
            Dx[i*m_row + j] = obj.m_ptr[i]; //obj赋值给第j列
        }

        //for( int i=0;i<m_row;i++) //print
        //{
        //    for(int j=0; j<m_row;j++)
        //    {
        //        cout<< Dx[i*m_row+j]<<"\t";
        //    }
        //    cout<<endl;
        //}
        ret[j][0] = calcDet(m_row, Dx) / D;

    }

    delete[]Dx;
    return ret;
}

Matrix Matrix::getrow(Index_T index)//返回行
{
    Matrix ret(1, m_col); //一行的返回值

    for (Index_T i = 0; i< m_col; i++)
    {

         ret[0][i] = m_ptr[(index) *m_col + i] ;

    }
    return ret;
}

Matrix Matrix::getcol(Index_T index)//返回列
{
    Matrix ret(m_row, 1); //一列的返回值


    for (Index_T i = 0; i< m_row; i++)
    {

        ret[i][0] = m_ptr[i *m_col + index];

    }
    return ret;
}

Matrix Matrix::exponent(double x)//每个元素x次幂
{
    Matrix ret(m_row, m_col);
    for (Index_T i = 0; i< m_row; i++)
    {
        for (Index_T j = 0; j < m_col; j++)
        {
            ret[i][j]= pow(m_ptr[i*m_col + j],x);
        }
    }
    return ret;
}
void Matrix::maxlimit(double max, double set)//每个元素x次幂
{

    for (Index_T i = 0; i< m_row; i++)
    {
        for (Index_T j = 0; j < m_col; j++)
        {
            m_ptr[i*m_col + j] = m_ptr[i*m_col + j]>max ? 0 : m_ptr[i*m_col + j];
        }
    }

}
Matrix Matrix::eye()//对角阵
{

    for (Index_T i = 0; i< m_row; i++)
    {
        for (Index_T j = 0; j < m_col; j++)
        {
            if (i == j)
            {
                m_ptr[i*m_col + j] = 1.0;
            }
        }
    }
    return *this;
}
void Matrix::zeromean(_In_opt_  bool flag)
{
    if (flag == true) //计算列均值
    {
        double *mean = new double[m_col];
        for (Index_T j = 0; j < m_col; j++)
        {
            mean[j] = 0.0;
            for (Index_T i = 0; i < m_row; i++)
            {
                mean[j] += m_ptr[i*m_col + j];
            }
            mean[j] /= m_row;
        }
        for (Index_T j = 0; j < m_col; j++)
        {

            for (Index_T i = 0; i < m_row; i++)
            {
                m_ptr[i*m_col + j] -= mean[j];
            }
        }
        delete[]mean;
    }
    else //计算行均值
    {
        double *mean = new double[m_row];
        for (Index_T i = 0; i< m_row; i++)
        {
            mean[i] = 0.0;
            for (Index_T j = 0; j < m_col; j++)
            {
                mean[i] += m_ptr[i*m_col + j];
            }
            mean[i] /= m_col;
        }
        for (Index_T i = 0; i < m_row; i++)
        {
            for (Index_T j = 0; j < m_col; j++)
            {
                m_ptr[i*m_col + j] -= mean[i];
            }
        }
        delete[]mean;
    }
}

void Matrix::normalize(_In_opt_  bool flag)
{
    if (flag == true) //计算列均值
    {
        double *mean = new double[m_col];

        for (Index_T j = 0; j < m_col; j++)
        {
            mean[j] = 0.0;
            for (Index_T i = 0; i < m_row; i++)
            {
                mean[j] += m_ptr[i*m_col + j];
            }
            mean[j] /= m_row;
        }
        for (Index_T j = 0; j < m_col; j++)
        {

            for (Index_T i = 0; i < m_row; i++)
            {
                m_ptr[i*m_col + j] -= mean[j];
            }
        }
        ///计算标准差
        for (Index_T j = 0; j < m_col; j++)
        {
            mean[j] = 0;
            for (Index_T i = 0; i < m_row; i++)
            {
                mean[j] += pow(m_ptr[i*m_col + j],2);//列平方和
            }
                mean[j] = sqrt(mean[j] / m_row); // 开方
        }
        for (Index_T j = 0; j < m_col; j++)
        {
            for (Index_T i = 0; i < m_row; i++)
            {
                m_ptr[i*m_col + j] /= mean[j];//列平方和
            }
        }
        delete[]mean;
    }
    else //计算行均值
    {
        double *mean = new double[m_row];
        for (Index_T i = 0; i< m_row; i++)
        {
            mean[i] = 0.0;
            for (Index_T j = 0; j < m_col; j++)
            {
                mean[i] += m_ptr[i*m_col + j];
            }
            mean[i] /= m_col;
        }
        for (Index_T i = 0; i < m_row; i++)
        {
            for (Index_T j = 0; j < m_col; j++)
            {
                m_ptr[i*m_col + j] -= mean[i];
            }
        }
        ///计算标准差
        for (Index_T i = 0; i< m_row; i++)
        {
            mean[i] = 0.0;
            for (Index_T j = 0; j < m_col; j++)
            {
                mean[i] += pow(m_ptr[i*m_col + j], 2);//列平方和
            }
            mean[i] = sqrt(mean[i] / m_col); // 开方
        }
        for (Index_T i = 0; i < m_row; i++)
        {
            for (Index_T j = 0; j < m_col; j++)
            {
                m_ptr[i*m_col + j] /= mean[i];
            }
        }
        delete[]mean;
    }
}

double Matrix::det()
{
    if (m_col == m_row)
        return calcDet(m_row, m_ptr);
    else
    {
        cout << ("行列不相等无法计算") << endl;
        return 0;
    }
}
/
istream& operator>>(istream &is, Matrix &obj)
{
    for (Index_T i = 0; i<obj.m_size; i++)
    {
        is >> obj.m_ptr[i];
    }
    return is;
}

ostream& operator<<(ostream &out, Matrix &obj)
{
    for (Index_T i = 0; i < obj.m_row; i++) //打印逆矩阵
    {
        for (Index_T j = 0; j < obj.m_col; j++)
        {
            out << (obj[i][j]) << "\t";
        }
        out << endl;
    }
    return out;
}
ofstream& operator<<(ofstream &out, Matrix &obj)//打印逆矩阵到文件
{
    for (Index_T i = 0; i < obj.m_row; i++)
    {
        for (Index_T j = 0; j < obj.m_col; j++)
        {
            out << (obj[i][j]) << "\t";
        }
        out << endl;
    }
    return out;
}

Matrix& operator<<(Matrix &obj, const double val)
{
    *obj.m_ptr = val;
    obj.m_curIndex = 1;
    return obj;
}
Matrix& operator,(Matrix &obj, const double val)
{
    if( obj.m_curIndex == 0 || obj.m_curIndex > obj.m_size - 1 )
    {
        return obj;
    }
    *(obj.m_ptr + obj.m_curIndex) = val;
    ++obj.m_curIndex;
    return obj;
}

Matrix operator+(const Matrix& lm, const Matrix& rm)
{
    if (lm.m_col != rm.m_col || lm.m_row != rm.m_row)
    {
        Matrix temp(0, 0);
        temp.m_ptr = NULL;
        cout << "operator+(): 矩阵shape 不合适,m_col:"
            << lm.m_col << "," << rm.m_col << ".  m_row:" << lm.m_row << ", " << rm.m_row << endl;
        return temp; //数据不合法时候,返回空矩阵
    }
    Matrix ret(lm.m_row, lm.m_col);
    for (Index_T i = 0; i<ret.m_size; i++)
    {
        ret.m_ptr[i] = lm.m_ptr[i] + rm.m_ptr[i];
    }
    return ret;
}
Matrix operator-(const Matrix& lm, const Matrix& rm)
{
    if (lm.m_col != rm.m_col || lm.m_row != rm.m_row)
    {
        Matrix temp(0, 0);
        temp.m_ptr = NULL;
        cout << "operator-(): 矩阵shape 不合适,m_col:"
            <<lm.m_col<<","<<rm.m_col<<".  m_row:"<< lm.m_row <<", "<< rm.m_row << endl;

        return temp; //数据不合法时候,返回空矩阵
    }
    Matrix ret(lm.m_row, lm.m_col);
    for (Index_T i = 0; i<ret.m_size; i++)
    {
        ret.m_ptr[i] = lm.m_ptr[i] - rm.m_ptr[i];
    }
    return ret;
}
Matrix operator*(const Matrix& lm, const Matrix& rm)  //矩阵乘法
{
    if (lm.m_size == 0 || rm.m_size == 0 || lm.m_col != rm.m_row)
    {
        Matrix temp(0, 0);
        temp.m_ptr = NULL;
        cout << "operator*(): 矩阵shape 不合适,m_col:"
            << lm.m_col << "," << rm.m_col << ".  m_row:" << lm.m_row << ", " << rm.m_row << endl;
        return temp; //数据不合法时候,返回空矩阵
    }
    Matrix ret(lm.m_row, rm.m_col);
    for (Index_T i = 0; i<lm.m_row; i++)
    {
        for (Index_T j = 0; j< rm.m_col; j++)
        {
            for (Index_T k = 0; k< lm.m_col; k++)//lm.m_col == rm.m_row
            {
                ret.m_ptr[i*rm.m_col + j] += lm.m_ptr[i*lm.m_col + k] * rm.m_ptr[k*rm.m_col + j];
            }
        }
    }
    return ret;
}
Matrix operator*(double val, const Matrix& rm)  //矩阵乘 单数
{
    Matrix ret(rm.m_row, rm.m_col);
    for (Index_T i = 0; i<ret.m_size; i++)
    {
        ret.m_ptr[i] = val * rm.m_ptr[i];
    }
    return ret;
}
Matrix operator*(const Matrix&lm, double val)  //矩阵乘 单数
{
    Matrix ret(lm.m_row, lm.m_col);
    for (Index_T i = 0; i<ret.m_size; i++)
    {
        ret.m_ptr[i] = val * lm.m_ptr[i];
    }
    return ret;
}

Matrix operator/(const Matrix&lm, double val)  //矩阵除以 单数
{
    Matrix ret(lm.m_row, lm.m_col);
    for (Index_T i = 0; i<ret.m_size; i++)
    {
        ret.m_ptr[i] =  lm.m_ptr[i]/val;
    }
    return ret;
}
Matrix Matrix::multi(const Matrix&rm)// 对应元素相乘
{
    if (m_col != rm.m_col || m_row != rm.m_row)
    {
        Matrix temp(0, 0);
        temp.m_ptr = NULL;
        cout << "multi(const Matrix&rm): 矩阵shape 不合适,m_col:"
            << m_col << "," << rm.m_col << ".  m_row:" << m_row << ", " << rm.m_row << endl;
        return temp; //数据不合法时候,返回空矩阵
    }
    Matrix ret(m_row,m_col);
    for (Index_T i = 0; i<ret.m_size; i++)
    {
        ret.m_ptr[i] = m_ptr[i] * rm.m_ptr[i];
    }
    return ret;

}

Matrix&  Matrix::operator=(const Matrix& rhs)
{
    if (this != &rhs)
    {
        m_row = rhs.m_row;
        m_col = rhs.m_col;
        m_size = rhs.m_size;
        if (m_ptr != NULL)
            delete[] m_ptr;
        m_ptr = new double[m_size];
        for (Index_T i = 0; i<m_size; i++)
        {
            m_ptr[i] = rhs.m_ptr[i];
        }
    }
    return *this;
}
//||matrix||_2  求A矩阵的2范数
double Matrix::norm2()
{
    double norm = 0;
    for (Index_T i = 0; i < m_size; ++i)
    {
        norm += m_ptr[i] * m_ptr[i];
    }
    return (double)sqrt(norm);
}
double Matrix::norm1()
{
    double sum = 0;
    for (Index_T i = 0; i < m_size; ++i)
    {
        sum += abs(m_ptr[i]);
    }
    return sum;
}
double Matrix::mean()
{
    double sum = 0;
    for (Index_T i = 0; i < m_size; ++i)
    {
        sum += (m_ptr[i]);
    }
    return sum/m_size;
}




void Matrix::sort(bool flag)
{
    double tem;
    for (Index_T i = 0; i<m_size; i++)
    {
        for (Index_T j = i + 1; j<m_size; j++)
        {
            if (flag == true)
            {
                if (m_ptr[i]>m_ptr[j])
                {
                    tem = m_ptr[i];
                    m_ptr[i] = m_ptr[j];
                    m_ptr[j] = tem;
                }
            }
            else
            {
                if (m_ptr[i]<m_ptr[j])
                {
                    tem = m_ptr[i];
                    m_ptr[i] = m_ptr[j];
                    m_ptr[j] = tem;
                }
            }

        }
    }
}
Matrix Matrix::diag()
{
    if (m_row != m_col)
    {
        Matrix m(0);
        cout << "diag():m_row != m_col" << endl;
        return m;
    }
    Matrix m(m_row);
    for (Index_T i = 0; i<m_row; i++)
    {
        m.m_ptr[i*m_row + i] = m_ptr[i*m_row + i];
    }
    return m;
}
Matrix Matrix::T()const
{
    Matrix tem(m_col, m_row);
    for (Index_T i = 0; i<m_row; i++)
    {
        for (Index_T j = 0; j<m_col; j++)
        {
            tem[j][i] = m_ptr[i*m_col + j];// (*this)[i][j]
        }
    }
    return tem;
}
void  Matrix::QR(Matrix &Q, Matrix &R) const
{
    //如果A不是一个二维方阵,则提示错误,函数计算结束
    if (m_row != m_col)
    {
        printf("ERROE: QR() parameter A is not a square matrix!\n");
        return;
    }
    const Index_T N = m_row;
    double *a = new double[N];
    double *b = new double[N];

    for (Index_T j = 0; j < N; ++j)  //(Gram-Schmidt) 正交化方法
    {
        for (Index_T i = 0; i < N; ++i)  //第j列的数据存到a,b
            a[i] = b[i] = m_ptr[i * N + j];

        for (Index_T i = 0; i<j; ++i)  //第j列之前的列
        {
            R.m_ptr[i * N + j] = 0;  //
            for (Index_T m = 0; m < N; ++m)
            {
                R.m_ptr[i * N + j] += a[m] * Q.m_ptr[m *N + i]; //R[i,j]值为Q第i列与A的j列的内积
            }
            for (Index_T m = 0; m < N; ++m)
            {
                b[m] -= R.m_ptr[i * N + j] * Q.m_ptr[m * N + i]; //
            }
        }

        double norm = 0;
        for (Index_T i = 0; i < N; ++i)
        {
            norm += b[i] * b[i];
        }
        norm = (double)sqrt(norm);

        R.m_ptr[j*N + j] = norm; //向量b[]的2范数存到R[j,j]

        for (Index_T i = 0; i < N; ++i)
        {
            Q.m_ptr[i * N + j] = b[i] / norm; //Q 阵的第j列为单位化的b[]
        }
    }
    delete[]a;
    delete[]b;
}
Matrix Matrix::eig_val(_In_opt_ Index_T _iters)
{
    if (m_size == 0 || m_row != m_col)
    {
        cout << "矩阵为空或者非方阵!" << endl;
        Matrix rets(0);
        return rets;
    }
    //if (det() == 0)
    //{
    //  cout << "非满秩矩阵没法用QR分解计算特征值!" << endl;
    //  Matrix rets(0);
    //  return rets;
    //}
    const Index_T N = m_row;
    Matrix matcopy(*this);//备份矩阵
    Matrix Q(N), R(N);
    /*当迭代次数足够多时,A 趋于上三角矩阵,上三角矩阵的对角元就是A的全部特征值。*/
    for (Index_T k = 0; k < _iters; ++k)
    {
        //cout<<"this:\n"<<*this<<endl;
        QR(Q, R);
        *this = R*Q;
        /*  cout<<"Q:\n"<<Q<<endl;
        cout<<"R:\n"<<R<<endl;  */
    }
    Matrix val = diag();
    *this = matcopy;//恢复原始矩阵;
    return val;
}
Matrix Matrix::eig_vect(_In_opt_ Index_T _iters)
{
    if (m_size == 0 || m_row != m_col)
    {
        cout << "矩阵为空或者非方阵!" << endl;
        Matrix rets(0);
        return rets;
    }
    if (det() == 0)
    {
      cout << "非满秩矩阵没法用QR分解计算特征向量!" << endl;
      Matrix rets(0);
      return rets;
    }
    Matrix matcopy(*this);//备份矩阵
    Matrix eigenValue = eig_val(_iters);
    Matrix ret(m_row);
    const Index_T NUM = m_col;
    double eValue;
    double sum, midSum, diag;
    Matrix copym(*this);
    for (Index_T count = 0; count < NUM; ++count)
    {
        //计算特征值为eValue,求解特征向量时的系数矩阵
        *this = copym;
        eValue = eigenValue[count][count];

        for (Index_T i = 0; i < m_col; ++i)//A-lambda*I
        {
            m_ptr[i * m_col + i] -= eValue;
        }
        //cout<<*this<<endl;
        //将 this为阶梯型的上三角矩阵
        for (Index_T i = 0; i < m_row - 1; ++i)
        {
            diag = m_ptr[i*m_col + i];  //提取对角元素
            for (Index_T j = i; j < m_col; ++j)
            {
                m_ptr[i*m_col + j] /= diag; //【i,i】元素变为1
            }
            for (Index_T j = i + 1; j<m_row; ++j)
            {
                diag = m_ptr[j *  m_col + i];
                for (Index_T q = i; q < m_col; ++q)//消去第i+1行的第i个元素
                {
                    m_ptr[j*m_col + q] -= diag*m_ptr[i*m_col + q];
                }
            }
        }
        //cout<<*this<<endl;
        //特征向量最后一行元素置为1
        midSum = ret.m_ptr[(ret.m_row - 1) * ret.m_col + count] = 1;
        for (int m = m_row - 2; m >= 0; --m)
        {
            sum = 0;
            for (Index_T j = m + 1; j < m_col; ++j)
            {
                sum += m_ptr[m *  m_col + j] * ret.m_ptr[j * ret.m_col + count];
            }
            sum = -sum / m_ptr[m *  m_col + m];
            midSum += sum * sum;
            ret.m_ptr[m * ret.m_col + count] = sum;
        }
        midSum = sqrt(midSum);
        for (Index_T i = 0; i < ret.m_row; ++i)
        {
            ret.m_ptr[i * ret.m_col + count] /= midSum; //每次求出一个列向量
        }
    }
    *this = matcopy;//恢复原始矩阵;
    return ret;
}
Matrix Matrix::cov(bool flag)
{
    //m_row 样本数,column 变量数
    if (m_col == 0)
    {
        Matrix m(0);
        return m;
    }
    double *mean = new double[m_col]; //均值向量

    for (Index_T j = 0; j<m_col; j++) //init
    {
        mean[j] = 0.0;
    }
    Matrix ret(m_col);
    for (Index_T j = 0; j<m_col; j++) //mean
    {
        for (Index_T i = 0; i<m_row; i++)
        {
            mean[j] += m_ptr[i*m_col + j];
        }
        mean[j] /= m_row;
    }
    Index_T i, k, j;
    for (i = 0; i<m_col; i++) //第一个变量
    {
        for (j = i; j<m_col; j++) //第二个变量
        {
            for (k = 0; k<m_row; k++) //计算
            {
                ret[i][j] += (m_ptr[k*m_col + i] - mean[i])*(m_ptr[k*m_col + j] - mean[j]);

            }
            if (flag == true)
            {
                ret[i][j] /= (m_row-1);
            }
            else
            {
                ret[i][j] /= (m_row);
            }
        }
    }
    for (i = 0; i<m_col; i++) //补全对应面
    {
        for (j = 0; j<i; j++)
        {
            ret[i][j] = ret[j][i];
        }
    }
    return ret;
}

/*
 * 返回代数余子式
 */
double CalcAlgebraicCofactor( Matrix& srcMat, Index_T ai, Index_T aj)
{
    Index_T temMatLen = srcMat.row()-1;
    Matrix temMat(temMatLen);
    for (Index_T bi = 0; bi < temMatLen; bi++)
    {
        for (Index_T bj = 0; bj < temMatLen; bj++)
        {
            Index_T rowOffset = bi < ai ? 0 : 1;
            Index_T colOffset = bj < aj ? 0 : 1;
            temMat[bi][bj] = srcMat[bi + rowOffset][bj + colOffset];
        }
    }
    int flag = (ai + aj) % 2 == 0 ? 1 : -1;
    return flag * temMat.det();
}

/*
 * 返回伴随阵
 */
Matrix Matrix::adjoint()
{
    if (m_row != m_col)
    {
        return Matrix(0);
    }

    Matrix adjointMat(m_row);
    for (Index_T ai = 0; ai < m_row; ai++)
    {
        for (Index_T aj = 0; aj < m_row; aj++)
        {
            adjointMat.m_ptr[aj*m_row + ai] = CalcAlgebraicCofactor(*this, ai, aj);
        }
    }
    return adjointMat;
}

Matrix Matrix::inverse()
{
    double detOfMat = det();
    if (detOfMat == 0)
    {
        cout << "行列式为0,不能计算逆矩阵。" << endl;
        return Matrix(0);
    }
    return adjoint()/detOfMat;
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++矩阵运算类(Matrix.h) 的相关文章

随机推荐

  • 有了这款可视化算法项目,算法不再难!

    我的新书 Android App开发入门与实战 已于2020年8月由人民邮电出版社出版 欢迎购买 点击进入详情 GitHub严选 每天推荐一个GitHub优质开源项目 从不奢求生活能给予我最好的 只是执着于寻求最适合我的 大家好 我是严选哥
  • SpringBoot整合SpringData JPA详解

    本篇文章主要记录SpringBoot整合SpringData JPA 感兴趣的小伙伴和小编一起来学习吧 目录 1 添加依赖 2 编写一个实体类 3 编写一个Dao接口来操作实体类对应的数据表 4 application配置 5 编写接口 1
  • 分布式秒杀案例讲解教程文档

    程序员ken 一 准备工作 1 1 vmware软件安装 虚拟机 相关教程 http c biancheng net view 714 html 网络配置这块 1 进入网络配置文件目录 cd etc sysconfig network sc
  • 产品经理针对用户访谈获得的信息该如何理解吸收

    核心 他人的负反馈 吐槽 要认可 他人的正反馈 认可 要谨慎 以产品规划阶段为例 我们打算做一个产品 为了论证市场价值 我们会找相关的客用户开展用户访谈 根据事先准备的访谈大纲开展访谈 收集信息很容易 如何筛选 分析信息 这才是难点和关键
  • UE4数据写入Json格式

    用UE4写入Json很简单只需要使用 TSharedPtr
  • 散列(哈希)表

    1 如何构造散列函数 总结三点散列函数设计的基本要求 1 散列函数计算得到的散列值是一个非负整数 下标从0开始 2 如果key1 key2 那么hash key1 hash key2 相同的key经过hash 得到的散列值应该是相等的 3
  • 力扣刷题记录 -- JAVA---137--84. 柱状图中最大的矩形

    目录 一 题目 二 代码 三 运行结果 一 题目 二 代码 class Solution 类比贪心 局部最优到全局最优 左边第一个小于的下标 右边第一个小于的下标 public int largestRectangleArea int he
  • LeetCode-321.拼接最大数、单调栈

    给定长度分别为 m 和 n 的两个数组 其元素由 0 9 构成 表示两个自然数各位上的数字 现在从这两个数组中选出 k k lt m n 个数字拼接成一个新的数 要求从同一个数组中取出的数字保持其在原数组中的相对顺序 求满足该条件的最大数
  • Ubuntu系统查看镜像源并使用阿里云的镜像源

    Ubuntu系统查看镜像源并使用阿里云的镜像源 前言 查看系统镜像源 修改系统镜像源 测试与更新 前言 Ubuntu 使用 apt 管理系统级的包 软件非常方便 但由于这些托管包 软件的中央仓库基本都位于美国 所以对于国内用户来说因为洲际网
  • Windows powershell 正确初始化anaconda

    我安装的conda为miniconda 安装在E miniconda下 首先 在powershell中输入 powershell ExecutionPolicy ByPass NoExit Command E miniconda shell
  • springBoot输出日志到指定目录

    以输出日志文件到D data log为例 版本一 一 在application properties加上如下配置 logging path D data log logging config classpath logback spring
  • Vue自定义指令

    目录 1 自定义指令注册 1 1 全局注册 1 2 局部注册 2 自定义指令写法 2 1 对象式 常用 2 2 函数式 3 总结 1 自定义指令注册 1 1 全局注册 Vue directive name 1 2 局部注册 directiv
  • 计算机怎么更改桌面图标大小,win7系统桌面图标怎么设置大小 win7电脑桌面图标大小更改方法...

    win7系统在使用的时候不知道大家有没有遇上这样的问题 就是桌面图标的大小不符合我们的审美 那么遇上这种情况要怎么解决呢 下面小编就跟大家说说处理的方法 具体的解决方法 这种方法是最快捷的方法 我们可以在电脑桌面上 按住Ctrl键不放 然后
  • Qt 子线程中使用UI线程

    方案起源 最近做了一个Excel保存图表的项目 因为不能直接用Excel的图表 会直接暴露计算数据 所以采用的是QCharts生成的表格 但是QCharts的问题是 调用QChartView setChart接口之后 会出现不在同一个线程的
  • 模拟电路设计(5)--- J-FET的特性曲线

    上篇我们分析了J FET的结构和工作原理 今天我们来说说J FET的输出 转移特性曲线 J FET的输出特性曲线 由图中可以看出 J FET的输出特性曲线分为四个区域 可变电阻区 线性放大区 截止区和击穿区 下面分别来说说 1 截止区 在N
  • Vue第10天笔记:Vue动画(了解)、yarn命令的安装、webpack:介绍、基本步骤使用、npm中 --save和 --save-dev的区别、scripts的使用、配置到文件中、自动生成插件

    前一天复习 1 自定义指令 1 定义使用 Vue directive 指令名 指令的配置对象 2 五个钩子函数 bind inserted update 3 钩子函数的参数 el 指令所在的元素 binding 指令相关的信息对象 1 na
  • 【数模】奇异值分解SVD和图形处理

    介绍奇异值分解在图形压缩中的运用 并将简单介绍下Matlab对于图形和视频的处理 一 奇异值分解介绍 1 1 基本概念 奇异值分解 Singular Value Decomposition 以下简称SVD 是线性代数中一种重要的矩阵分解 U
  • C++ STL三大常用容器

    看到一篇文章觉得对不熟悉STL容器特性和使用选择的人来说很友好 就收藏和学习下 https blog csdn net qq 44943840 article details 121990808 C 中的容器可以分为好多种 常见的有顺序容器
  • 计算机网络(一)----概述

    概述 功能 组成 分类 性能指标 一 计算机网络的概述 1 网络的概念网络是由若干结点和链路组成 结点可以是计算机 集线器 交换机 路由器等 链路可以是有线链路或无线链路 如电信网络 电话 电报 传真服务 有限电视网络 观看电视节目 计算机
  • C++矩阵运算类(Matrix.h)

    这个类数据类型是double 包含了常用的矩阵计算 多数方法经过实践验证 也难免有不足之处 如有发现欢迎指出 https github com ims0 comTutor tree master matrix include