2008年某月写的矩阵Matrix模板类

头文件:

#pragma once
/*
用法:
1.通过数组构造矩阵
DATATYPE pD[]{1,2,3,4,5,6,7,8,9};
Matrix mat(pD,3,3);

mat[0][0]==1
mat[1][1]==3
2.通过文件构造矩阵
对该文件的要求为:第一行为此文件中的矩阵的 “[行数,列数]”;第二行开始为数据行,按“数字,数字,……,数字;”为一行
如matrix.txt:
[3,3]
1,2,3;
4,5,6;
7,8,9;
Matrix mat("C://matrix.txt");

注意事项:
方阵计算时会先检查是否能够进行运算,不匹配则会抛出char*类型的错误,需在调用时catch char*类型的信息
如:
DATATYPE pD[]={
   -1,0,0,1,
   0,1,0,1,
   0,0,1,2
};
Matrix mat1("C://matrix.txt");
Matrix mat2(pD, 4, 3);
Matrix mat3(pD, 3, 3);
cout<<"矩阵1:"<<endl;
mat1.Output();
cout<<"矩阵2:"<<endl;
mat2.Output();
cout<<"矩阵3:"<<endl;
mat3.Output();

if(mat1 == mat2) cout<< "矩阵1与2相同"<<endl;
else cout<< "矩阵1与2不同"<<endl;

try
{
   cout<<"矩阵1+矩阵3:"<<endl;  
   (mat1+mat3).Output();
   cout<<"矩阵1*矩阵3:"<<endl;  
   (mat1*mat3).Output();
   cout<<"矩阵2对应行列式的值:"<<mat2.DeterminantValue()<<endl;
   mat2.ReverseMatrix().Output();  
}
catch(char *c)
{
   cout<<c<<endl;
}
4.最新更新,将Array,Matrix修改为模板类,应用时可将上述的Matrix分别替换为MatrixChar,MatrixInt,MatrixDouble来使用
*/

#include <string>
#include <iostream>
#include <fstream>
#include <math.h>
using namespace std;

#define NULL 0
//默认行数
#define DEFAULTROW 0
//默认列数
#define DEFAULTCOL 0
//默认矩阵输入文件
#define DEFAULTOPENPATH "C://matrix.txt"
//默认矩阵计算结果保存路径
#define DEFAULTSAVEPATH "C://calcMatrix.txt"
//数据保存到文件时,所采取的文件打开方式
#define SAVEFILEOPENMODE ios_base::out|ios_base::app

//typedef double DATATYPE;

//Array类定义
template <class DATATYPE>
class Array
{
private:
int m_size;
DATATYPE* m_pointer;
DATATYPE m_aver, m_cov;
bool m_isCalcAver,m_isCalcCov;
void InitBuffer(int n){m_size = n; m_pointer=new DATATYPE[n];}
public:
Array<DATATYPE>(int n){InitBuffer(n); m_isCalcAver=m_isCalcCov=m_aver=m_cov=0;}
Array<DATATYPE>(){m_size=0; m_pointer=NULL; m_isCalcAver=m_isCalcCov=m_aver=m_cov=0;}
Array<DATATYPE>(DATATYPE* pDobule, int n=DEFAULTCOL){InitBuffer(n); SetElements(pDobule); m_isCalcAver=m_isCalcCov=m_aver=m_cov=0;}
Array<DATATYPE>(Array<DATATYPE>& arr){InitBuffer(arr.m_size);SetElements(arr.m_pointer); m_isCalcAver=m_isCalcCov=m_aver=m_cov=0;}
Array<DATATYPE> operator=(Array<DATATYPE>& arr){SetElements(arr.m_pointer); return *this;}
~Array(){if(m_pointer!=NULL) delete[] m_pointer;}
DATATYPE& operator[](int n){return m_pointer[n];}
void SaveData(iostream& out)
{
   //输出全部数据成员
   for(int i=0;i<m_size;i++)
    out<<m_pointer[i]<<',';
   out<<'/t';
   if(!m_isCalcAver) out<<"未计算过均值/t";
   else out<<"均值:"<<m_aver<<'/t';
   if(!m_isCalcCov) out<<"未计算过协方差/t";
   else out<<"协方差:"<<m_cov;
}
operator DATATYPE*(){return m_pointer;}
void SetSize(int n)
{
   if(n == m_size) return;
   if(m_pointer) delete [] m_pointer;
   m_pointer=new DATATYPE[n];
   m_size = n;
}
void SetElements(DATATYPE value)
{
   for(int i=0; i<m_size;i++)
    m_pointer[i]=value;
}
void SetElements(DATATYPE *pDATATYPE)
{
   for(int i=0; i<m_size;i++)
    m_pointer[i]=pDATATYPE[i];
}
DATATYPE Average()//平均值
{
   DATATYPE sum=0;
   for(int i=0;i<m_size;i++) sum += m_pointer[i];
   return m_aver=sum/m_size;
}
DATATYPE Covariance(Array<DATATYPE>& arr)//协方差
{
   DATATYPE aver1, aver2, sum=0;
   aver1 = Average();
   aver2 = arr.Average();
   for(int i=0; i<m_size; i++)
    sum += (m_pointer[i]-aver1)*(arr[i]-aver2);
   return m_cov=sum/(m_size-1);
}
Array<DATATYPE> & Add(Array<DATATYPE> & arr)
{
   for(int i=0; i<m_size; i++)
    m_pointer[i] += arr[i];
   return *this;
}
Array<DATATYPE>& operator+(Array<DATATYPE>& arr){return Add(arr);}
Array<DATATYPE>& Sub(Array<DATATYPE>& arr)
{
   for(int i=0;i<m_size;i++) m_pointer[i]-=arr[i];
   return *this;
}
Array<DATATYPE>& operator-(Array<DATATYPE>& arr){return Sub(arr);}
Array<DATATYPE>& Multiply(DATATYPE d)
{
   for(int i=0;i<m_size;i++) m_pointer[i]*=d;
   return *this;
}
Array<DATATYPE>& operator*(DATATYPE d){return Multiply(d);}
Array<DATATYPE>& operator*=(DATATYPE d){return Multiply(d);}
};

//matrix类定义
template <class DATATYPE>
class Matrix
{
private:
int m_row, m_col;
string m_strSavePath;
Array<DATATYPE> * m_pArray;
void InitBuffer(int row, int col)
{
   m_row = row;   m_col = col;
   m_pArray = new Array<DATATYPE>[row];
   for(int i=0; i<row; i++)
    m_pArray[i].SetSize(col);
}
void DeleteBuffer()
{
   delete[] m_pArray;
   m_pArray = NULL;
   m_row = m_col = 0;
}
public:
Matrix<DATATYPE>(int row, int col);
Matrix<DATATYPE>(char* strFileName=DEFAULTOPENPATH);//从文件输入矩阵的构造函数
Matrix<DATATYPE>(DATATYPE *pDATATYPE, int row, int col);//通过数组输入矩阵的构造函数
//Matrix(DATATYPE **ppDATATYPE, int row=DEFAULTROW, int col=DEFAULTCOL);
Matrix<DATATYPE>(Matrix<DATATYPE>& mat);//拷贝构造函数
Matrix<DATATYPE>& operator=(Matrix<DATATYPE>& mat);//重载赋值运算符
~Matrix();//保存计算结果
int GetRow(){return m_row;}
int GetCol(){return m_col;}
void SetSize(int row, int col)
{
   if(row==m_row&&col==m_col)
    return;
   DeleteBuffer();
   InitBuffer(row, col);
}
void SetElements(DATATYPE value)//将元素统一设置为同一个值
{
   for(int i=0;i<m_row;i++)
    m_pArray[i].SetElements(value);
}
void SetElements(DATATYPE *pDATATYPE)
{
   for(int i=0;i<m_row;i++)
   {
    m_pArray[i].SetElements(pDATATYPE);
    pDATATYPE += m_col;
   }
}
string GetSavePath(){return m_strSavePath;}
void SetSavePath(string strPath){m_strSavePath = strPath;}

Array<DATATYPE>& operator[](int row){return m_pArray[row];}
bool IsEqual(Matrix<DATATYPE>& mat);
bool operator==(Matrix<DATATYPE>& mat){return IsEqual(mat);}
//bool operator!=(Matrix& mat){return !IsEqual(mat);}

Matrix<DATATYPE> Add(Matrix<DATATYPE>& mat);
Matrix<DATATYPE> operator+(Matrix<DATATYPE>& mat){return Add(mat);}
Matrix<DATATYPE> operator+=(Matrix<DATATYPE>& mat){return Add( mat);}
Matrix<DATATYPE> Sub(Matrix<DATATYPE>& mat);
Matrix<DATATYPE> operator-(Matrix<DATATYPE>& mat){return Sub(mat);}
Matrix<DATATYPE> operator-=(Matrix<DATATYPE>& mat){return Sub(mat);}
Matrix<DATATYPE> Multiply(Matrix<DATATYPE>& mat);//矩阵相乘
Matrix<DATATYPE> operator*(Matrix<DATATYPE>& mat){return Multiply(mat);}
Matrix<DATATYPE> operator*=(Matrix<DATATYPE>& mat){return Multiply(mat);}
Matrix<DATATYPE> Multiply(DATATYPE d);//乘以单个数
Matrix<DATATYPE> operator*(DATATYPE d){return Multiply(d);}
Matrix<DATATYPE> operator*=(DATATYPE d){return Multiply(d);}
/*
Matrix<DATATYPE> Average();//求均值,即第一行的值的均值,结果为row*1的矩阵
Matrix<DATATYPE> Covariance();//求协方差
*/
DATATYPE SDET(DATATYPE a[], int n);
DATATYPE DeterminantValue();//行列式的值
int RINV(DATATYPE a[], int n);
Matrix<DATATYPE> ReverseMatrix();//方阵的逆矩阵

void Output()
{
   for(int i=0;i<m_row;i++)
   {
    for(int j=0;j<m_col;j++)
     cout<<m_pArray[i][j]<<' ';
    cout<<endl;
   }
}
};

typedef Matrix<char> MatrixChar;
typedef Matrix<int> MatrixInt;
typedef Matrix<double> MatrixDouble;

 

 

实现文件(包括main入口函数):

// Matrix.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "./matrix.h"

int _tmain(int argc, _TCHAR* argv[])
{
double pI[]={
   1,0,0,
   0,1,0,
   0,0,1
};
MatrixDouble mat1(pI, 3, 3);

double pD[]={
   -1,0,0,1,
   0,1,0,1,
   0,0,1,2
};
MatrixDouble mat2(pD, 3, 4);
MatrixDouble mat3(DEFAULTOPENPATH);

cout<<"矩阵1:"<<endl;
mat1.Output();
cout<<"矩阵2:"<<endl;
mat2.Output();
cout<<"文件矩阵:"<<endl;
mat3.Output();

if(mat2 == mat3) cout<< "矩阵2与矩阵3相同"<<endl;
else cout<< "矩阵2与矩阵3不同"<<endl;

if(mat1 == mat3) cout<< "矩阵1与矩阵3相同"<<endl;
else cout<< "矩阵1与矩阵3不同"<<endl;

try
{
   cout<<"矩阵1+矩阵3:"<<endl;
   (mat1 + mat3).Output();
   cout<<"矩阵1*矩阵3:"<<endl;  
   (mat1*mat3).Output();
   cout<<"矩阵1对应行列式的值:"<<mat1.DeterminantValue()<<endl;
   cout<<"矩阵1的逆阵:"<<endl;
   mat1.ReverseMatrix().Output();  
}
catch(char *c)
{
   cout<<c<<"——程序终止、退出!"<<endl;
}

return 0;
}

template <class DATATYPE>
Matrix<DATATYPE>::Matrix(int row, int col)
{
InitBuffer(row, col);
m_strSavePath=DEFAULTSAVEPATH;
}

template <class DATATYPE>
Matrix<DATATYPE>::Matrix(DATATYPE *pDATATYPE, int row, int col)
//要求矩阵数据保存在pDATATYPE的一维数组中
{
InitBuffer(row, col);
m_strSavePath = DEFAULTSAVEPATH;
SetElements(pDATATYPE);
}
/*
Matrix::Matrix(DATATYPE **ppDATATYPE, int row, int col)
//要求矩阵数据保存在ppDATATYPE的二维数组中
{
InitBuffer(row, col);
m_strSavePath = DEFAULTSAVEPATH;
SetElements((DATATYPE*)ppDATATYPE);
}
*/
template <class DATATYPE>
Matrix<DATATYPE>::Matrix(char* strFileName)
/*通过文件strFileName来输入矩阵数据
对该文件的要求为:第一行为此文件中的矩阵的 “[行数,列数]”;第二行开始为数据行,按“数字,数字,……,数字;”为一行
如matrix.txt:
[3,3]
1,2,3;
4,5,6;
7,8,9;
*/
{
DATATYPE d;
char a;
int row,col;
fstream file;
file.open(strFileName, ios_base::in);
file>>a>>row>>a>>col>>a;
InitBuffer(row, col);
m_strSavePath = DEFAULTSAVEPATH;
for(int i=0; i<row; i++)
   for(int j=0; j<col; j++)
   {
    file>>d>>a;
    this->m_pArray[i][j] = d;
   }
file.close();
}

template <class DATATYPE>
Matrix<DATATYPE>::Matrix(Matrix& mat)
{
this->InitBuffer(mat.GetRow(), mat.GetCol());
this->SetSavePath(mat.GetSavePath());
for(int i=0;i<m_row;i++)
   this->m_pArray[i] = mat[i];
}

template <class DATATYPE>
Matrix<DATATYPE>& Matrix<DATATYPE>::operator=(Matrix& mat)
{
this->DeleteBuffer();
this->InitBuffer(mat.GetRow(), mat.GetCol());
this->SetSavePath(mat.GetSavePath());
for(int i=0;i<m_row;i++)
   this->m_pArray[i] = mat[i];
return *this;
}

template <class DATATYPE>
Matrix<DATATYPE>::~Matrix()
{
//保存计算结果
fstream file;
file.open(m_strSavePath.c_str(), SAVEFILEOPENMODE);
for(int i=0; i<m_row; i++)
{
   m_pArray[i].SaveData(file);
   file<<endl;
}
file.close();
//删除数据所占用空间
DeleteBuffer();
}

template <class DATATYPE>
bool Matrix<DATATYPE>::IsEqual(Matrix<DATATYPE>& mat)
{
if(m_row!=mat.m_row || m_col!=mat.m_col) return false;
for(int i=0; i<m_row; i++)
   for(int j=0; j<m_col; j++)
    if(this->m_pArray[i][j] != mat[i][j]) return false;
return true;
}
/*
Matrix<DATATYPE> Matrix<DATATYPE>::Average()//求行均值
{
Matrix<DATATYPE> newmat(m_row, 1);
for(int i=0; i<m_row; i++)
   newmat[i][0] = this->m_pArray[i].Average();
return newmat;
}

Matrix<DATATYPE> Matrix<DATATYPE>::Covariance()//求协方差
{
Matrix<DATATYPE> newmat(m_row, m_col);
return newmat;
}
*/
template <class DATATYPE>
DATATYPE Matrix<DATATYPE>::DeterminantValue()//行列式的值
{
if(m_row != m_col) throw("不是方阵!不能计算对应行列式值。");
DATATYPE re, *pD;
pD=new DATATYPE[m_row*m_row];
for(int i=0; i<m_row; i++)
   for(int j=0; j<m_row; j++)
    pD[i*m_row+j] = this->m_pArray[i][j];
re = SDET(pD, m_row);
delete [] pD;
return re;
}

template <class DATATYPE>
Matrix<DATATYPE> Matrix<DATATYPE>::ReverseMatrix()//方阵的逆矩阵
{
if(m_row != m_col) throw("不是方阵!不能计算逆阵。");
DATATYPE *pD;
pD=new DATATYPE[m_row*m_row];
for(int i=0; i<m_row; i++)
   for(int j=0; j<m_row; j++)
    pD[i*m_row+j] = this->m_pArray[i][j];
if(!RINV(pD, m_row)) throw("逆阵不存在!");
Matrix<DATATYPE> newmat(pD, m_row, m_row);
delete [] pD;
return newmat;
}

template <class DATATYPE>
DATATYPE Matrix<DATATYPE>::SDET(DATATYPE a[], int n)
{ int i,j,k,is,js,l,u,v;
    DATATYPE f,det,q,d;
    f=1.0; det=1.0;
    for (k=0; k<=n-2; k++)
      { q=0.0;
        for (i=k; i<=n-1; i++)
        for (j=k; j<=n-1; j++)
          { l=i*n+j; d=fabs(a[l]);
     if (d>q) { q=d; is=i; js=j;}
          }
        if (q+1.0==1.0)
          { det=0.0; return(det);}
        if (is!=k)
          { f=-f;
            for (j=k; j<=n-1; j++)
              { u=k*n+j; v=is*n+j;
                d=a[u]; a[u]=a[v]; a[v]=d;
              }
          }
        if (js!=k)
          { f=-f;
            for (i=k; i<=n-1; i++)
              { u=i*n+js; v=i*n+k;
                d=a[u]; a[u]=a[v]; a[v]=d;
              }
          }
        l=k*n+k;
        det=det*a[l];
        for (i=k+1; i<=n-1; i++)
          { d=a[i*n+k]/a[l];
            for (j=k+1; j<=n-1; j++)
              { u=i*n+j;
                a[u]=a[u]-d*a[k*n+j];
              }
          }
      }
    det=f*det*a[n*n-1];
    return(det);
}

template <class DATATYPE>
int Matrix<DATATYPE>::RINV(DATATYPE a[], int n)
{ int *is,*js,i,j,k,l,u,v;
    DATATYPE d,p;
    is=(int*)malloc(n*sizeof(int));
    js=(int*)malloc(n*sizeof(int));
    for (k=0; k<=n-1; k++)
      { d=0.0;
        for (i=k; i<=n-1; i++)
        for (j=k; j<=n-1; j++)
          { l=i*n+j; p=fabs(a[l]);
            if (p>d) { d=p; is[k]=i; js[k]=j;}
          }
        if (d+1.0==1.0)
          { free(is); free(js);
            return(0);
          }
        if (is[k]!=k)
          for (j=0; j<=n-1; j++)
            { u=k*n+j; v=is[k]*n+j;
              p=a[u]; a[u]=a[v]; a[v]=p;
            }
        if (js[k]!=k)
          for (i=0; i<=n-1; i++)
            { u=i*n+k; v=i*n+js[k];
              p=a[u]; a[u]=a[v]; a[v]=p;
            }
        l=k*n+k;
        a[l]=1.0/a[l];
        for (j=0; j<=n-1; j++)
          if (j!=k)
            { u=k*n+j; a[u]=a[u]*a[l];}
        for (i=0; i<=n-1; i++)
          if (i!=k)
            for (j=0; j<=n-1; j++)
              if (j!=k)
                { u=i*n+j;
                  a[u]=a[u]-a[i*n+k]*a[k*n+j];
                }
        for (i=0; i<=n-1; i++)
          if (i!=k)
            { u=i*n+k; a[u]=-a[u]*a[l];}
      }
    for (k=n-1; k>=0; k--)
      { if (js[k]!=k)
          for (j=0; j<=n-1; j++)
            { u=k*n+j; v=js[k]*n+j;
              p=a[u]; a[u]=a[v]; a[v]=p;
            }
        if (is[k]!=k)
          for (i=0; i<=n-1; i++)
            { u=i*n+k; v=i*n+is[k];
              p=a[u]; a[u]=a[v]; a[v]=p;
            }
      }
    free(is); free(js);
    return(1);
}
//Matrix的运算函数实现
template <class DATATYPE>
Matrix<DATATYPE> Matrix<DATATYPE>::Add(Matrix<DATATYPE>& mat)
{
if(m_row!=mat.m_row || m_col!=mat.m_col) throw("两阵规格不同!不能相加。");
Matrix<DATATYPE> newmat(*this);
for(int i=0; i<m_row; i++) newmat[i].Add(mat[i]);
return newmat;
}

template <class DATATYPE>
Matrix<DATATYPE> Matrix<DATATYPE>::Sub(Matrix<DATATYPE>& mat)
{
if(m_row!=mat.m_row || m_col!=mat.m_col) throw("两阵规格不同!不能相减。");
Matrix<DATATYPE> newmat(*this);
for(int i=0;i<m_row;i++) newmat[i].Sub(mat[i]);
return newmat;
}

template <class DATATYPE>
Matrix<DATATYPE> Matrix<DATATYPE>::Multiply(DATATYPE d)
{
Matrix<DATATYPE> newmat(*this);
for(int i=0; i<m_row; i++)
   newmat[i] *= d;
return newmat;
}

template <class DATATYPE>
Matrix<DATATYPE> Matrix<DATATYPE>::Multiply(Matrix<DATATYPE>& mat)
{
if(m_col != mat.m_row) throw("两阵规格不匹配!不能相乘。");
Matrix<DATATYPE> newmat(m_row, mat.m_col);
for(int i=0; i<m_row; i++)
   for(int j=0; j<mat.m_col; j++)
   {
    DATATYPE sum=0;
    for(int k=0; k<m_col; k++)
     sum += m_pArray[i][k] * mat[k][j];
    newmat[i][j] = sum;
   }
return newmat;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值