CMatrix类 矩阵类 C++

不是我写的,仅分享学习!书上配套,如有侵权,速删

与测绘程序设计配套(C++) 矩阵类 ,这个类鲁棒性不好

矩阵运算类我更推荐eigen类,自行百度

代码:

matrix.h :

#pragma once
class matrix
{
public:
	matrix(int row=3,int col=3);
	// copy constructor

    matrix (const matrix& m);

	~matrix(void);
private:
	double **dMatData;//保存矩阵元素数据的二维数组
	int iRow;//矩阵的行
	int iCol;//矩阵的列
    
public:
	int Row() const {return iRow;}//返回行
	int Col() const {return iCol;}//返回列
    void SetSize (int row, int col);//调整数组的大小,原有数据不变(未测试)

	double& operator () (int row, int col);//获取矩阵元素
    double  operator () (int row, int col) const;//重载获取矩阵元素函数,只有const对象能访问
	matrix& operator = (const matrix& m) ;
    
    //注意:友元函数并不是类自己的成员函数
    friend matrix operator + (const matrix& m1,const matrix& m2);
	friend matrix operator - (const matrix& m1,const matrix& m2);
	friend matrix operator * (const matrix& m1,const matrix& m2);
	friend matrix operator * (const double& num, const matrix& m1);
	friend matrix operator * (const matrix& m1,const double& num);

	friend matrix operator ~ (const matrix& m);//矩阵转置
	matrix Inv();//矩阵求逆
	void Unit();//生成单位矩阵
};



matix.cpp :


#include "StdAfx.h"
#include "matrix.h"
#include "math.h"

matrix::matrix(int row,int col)
{
	iRow=row;
	iCol=col;
    dMatData = new double*[row];

	for (int i=0; i < row; i++)
	{
		dMatData[i]= new double[col];
		for(int j=0;j<col;j++)
		{
				dMatData[i][j]=0;
		}
	 }
}

// copy constructor,
//拷贝构造函数的作用:
//(1)以类对象作为函数参数传值调用时;
//(2)函数返回值为类对象;
//(3)用一个已定义的对象去初始化一个新对象时;

matrix::matrix (const matrix& m)
{
   	iRow=m.Row();
	iCol=m.Col();
    dMatData = new double*[iRow];

	for (int i=0; i < iRow; i++)
	{
		dMatData[i]= new double[iCol];
	//	for(int j=0;j<iCol;j++)
		{
			memcpy(dMatData[i],m.dMatData[i],sizeof(double)*iCol);
		}
	 }
   
}

matrix::~matrix(void)
{
    for (int i=0; i < iRow; i++)
	{
		delete[] dMatData[i];
	 }
	delete[] dMatData;
}

//返回数组元素(引用返回)
double& matrix::operator () (int row, int col)
{
    if (row >= iRow || col >= iCol)
	{
      throw( "matrix::operator(): Index out of range!");
	}
	
    return dMatData[row][col]; 
}

返回数组元素(重载)
double matrix::operator () (int row, int col) const
{
    if (row >= iRow || col >= iCol)
	{
      throw( "matrix::operator(): Index out of range!");
	}
	
    return dMatData[row][col]; 
}


//重载预算符+
matrix operator + (const matrix& m1,const matrix& m2)
{

   if((m1.Col()!=m2.Col()) ||(m1.Row()!=m2.Row()) )
   {
       throw( "matrix::operator+: The two matrix have different size!");
   }

   matrix matTmp(m1.Row(),m1.Col());
   for(int i=0;i<m1.Row();i++)
   {
	   for(int j=0;j<m1.Col();j++)
	   {
             matTmp(i,j)=m1(i,j)+m2(i,j);     
	   }
   }
   return matTmp;
}

//重载赋值运算符=,当左右两边矩阵的大小不相等时,
//以右边的大小为基准,调整左边矩阵的大小

matrix &matrix::operator = (const matrix& m) 
{
	//revised in 2011-4-1, by Daiwujiao
 //   if(iRow!=m.Row()||iCol!=m.Col())
	//{
 //       throw( "matrix::operator=: The two matrix have different size!");
	//}

	if(iRow!=m.Row()||iCol!=m.Col())
	{
		SetSize(m.Row(),m.Col());
	}
	for (int i=0; i < iRow; i++)
	{
		
		for(int j=0;j<iCol;j++)
		{
				dMatData[i][j]=m(i,j);
		}
	 }
    return *this;
}


//调整矩阵大小,原有值不变
void matrix::SetSize (int row, int col)
{
   if (row == iRow && col == iCol)
   {
      return;
   }

   double **rsData = new double*[row];
   	for (int i=0; i < row; i++)
	{
		rsData[i]= new double[col];
		for(int j=0;j<col;j++)
		{
				rsData[i][j]=0;
		}
	 }

	int minRow=(iRow>row)?row:iRow;
    int minCol= (iCol>col)?col:iCol;
    int  colSize = minCol * sizeof(double);
    

   for (int i=0; i < minRow; i++)
   {
      memcpy( rsData[i], dMatData[i], colSize);
   }

    for (int i=0; i < minRow; i++)
	{
         delete[] dMatData[i];
	}
	delete[] dMatData;
	dMatData=rsData;
    iRow=row;
	iCol=col;
    return;
}
//重载预算符-
matrix operator - (const matrix& m1,const matrix& m2)
{

   if((m1.Col()!=m2.Col()) ||(m1.Row()!=m2.Row()) )
   {
       throw( "matrix::operator-: The two matrix have different size!");
   }

   matrix matTmp(m1.Row(),m1.Col());
   for(int i=0;i<m1.Row();i++)
   {
	   for(int j=0;j<m1.Col();j++)
	   {
             matTmp(i,j)=m1(i,j)-m2(i,j);     
	   }
   }
   return matTmp;
}

//重载预算符*,两个矩阵相乘,m1的列要等于m2的行
matrix operator * (const matrix& m1,const matrix& m2)
{

   if((m1.Col()!=m2.Row()))
   {
       throw( "matrix::operator*: The col of matrix m1 doesn't equ to row of m2 !");
   }

   matrix matTmp(m1.Row(),m2.Col());
   for(int i=0;i<m1.Row();i++)
   {
	   for(int j=0;j<m2.Col();j++)
	   {
		   for(int k=0;k<m2.Row();k++)
		   {
             matTmp(i,j)+=m1(i,k)*m2(k,j);     
		   }
	   }
   }
   return matTmp;
}

//重载预算符*,矩阵右乘一个数
matrix operator * (const matrix& m1,const double& num)
{
   matrix matTmp(m1.Row(),m1.Col());
   for(int i=0;i<m1.Row();i++)
   {
	   for(int j=0;j<m1.Col();j++)
	   {
             matTmp(i,j)=m1(i,j)*num;     

	   }
   }
   return matTmp;
}

//重载预算符*,矩阵左乘一个数
matrix operator * (const double& num, const matrix& m1)
{
   matrix matTmp(m1.Row(),m1.Col());
   for(int i=0;i<m1.Row();i++)
   {
	   for(int j=0;j<m1.Col();j++)
	   {
             matTmp(i,j)=m1(i,j)*num;     
	   }
   }
   return matTmp;
}

//矩阵转置
matrix operator ~ (const matrix& m)
{
  matrix matTmp(m.Col(),m.Row());

   for (int i=0; i < m.Row(); i++)
      for (int j=0; j < m.Col(); j++)
      {
         matTmp(j,i) = m(i,j);
      }
   return matTmp;
}


//矩阵求逆
//采用选全主元法
matrix matrix::Inv()
{
    if (iRow!=iCol)
	{
        throw("待求逆的矩阵行列不相等!");
	}
    
    int i, j, k, vv;
 
    matrix InvMat(iRow,iRow);

    //复制矩阵
	InvMat=*this;
   
    int* MainRow=new int[iRow];
	int* MainCol=new int[iRow];//用于记录主元素的行和列

    double dMainCell;//主元元素的值
    double dTemp;//临时变量

    for(k = 0;k<iRow;k++)
	{
        dMainCell = 0;
        //选全主元
        for( i = k;i<iRow ;i++)
		{
            for( j = k;j<iRow;j++)
			{
                dTemp = fabs(InvMat(i, j));
                if(dTemp > dMainCell)
				{
                    dMainCell = dTemp;
                    MainRow[k] = i;
                    MainCol[k] = j;
				}
			}
		}

		if( fabs(dMainCell) < 0.0000000000001)//矩阵秩亏,不能求逆
		{
            throw("矩阵秩亏");
		}

        if(MainRow[k] != k)//交换行
		{
            for( j = 0 ;j<iRow;j++)
			{
                vv = MainRow[k];
                dTemp = InvMat(k, j);
                InvMat(k, j) = InvMat(vv, j);
                InvMat(vv, j) = dTemp;
			}
		}

        if(MainCol[k] != k)//交换列
		{
            for(i = 0;i<iRow;i++)
			{
                vv = MainCol[k];
                dTemp = InvMat(i, k);
                InvMat(i, k) = InvMat(i, vv);
                InvMat(i, vv) = dTemp;
			}
		}
        InvMat(k, k) = 1.0 / InvMat(k, k);//计算乘数

        for( j = 0;j< iRow;j++) //计算主行
		{
            if(j != k)
			{
                InvMat(k, j) = InvMat(k, j) * InvMat(k, k);
			}
		}
        for(i = 0;i<iRow;i++)//消元
		{
            if( i !=k)
			{
                for(j = 0;j<iRow;j++)
				{
					if(j != k)
					{
                        InvMat(i, j) -= InvMat(i, k) * InvMat(k, j);
					}
				}
			}
		}
        for( i = 0;i< iRow;i++ )//计算主列
		{
            if( i != k)
			{
				InvMat(i, k) = -InvMat(i, k) * InvMat(k, k);
			}
		}
	}

    for( k = iRow - 1;k>=0;k--)
	{
        if(MainCol[k] != k)// 交换行
		{
            for( j = 0;j<iRow;j++)
			{
                vv = MainCol[k];
                dTemp = InvMat(k, j);
                InvMat(k, j) = InvMat(vv, j);
                InvMat(vv, j) = dTemp;
			}
		}

        if(MainRow[k] != k)//交换列
		{
            for( i = 0;i<iRow;i++)
			{
				vv = MainRow[k];
                dTemp = InvMat(i, k);
                InvMat(i, k) = InvMat(i, vv);
                InvMat(i, vv) = dTemp;
			}
		}
	}
	delete[] MainRow;
	delete[] MainCol;
    return InvMat;
}
//单位化矩阵
void matrix::Unit()
{
     for(int i=0;i<iRow;i++)
	 {
		 for(int j=0;j<iCol;j++)
		 {
			 dMatData[i][j]=(i==j)?1:0;
		 }
	 }
}


Introduction ============ This is a class for symmetric matrix related computations. It can be used for symmetric matrix diagonalization and inversion. If given the covariance matrix, users can utilize the class for principal component analysis(PCA) and fisher discriminant analysis(FDA). It can also be used for some elementary matrix and vector computations. Usage ===== It's a C++ program for symmetric matrix diagonalization, inversion and principal component anlaysis(PCA). To use it, you need to define an instance of CMatrix class, initialize matrix, call the public funtions, and finally, free the matrix. For example, for PCA, CMarix theMat; // define CMatrix instance float** C; // define n*n matrix C = theMat.allocMat( n ); Calculate the matrix (e.g., covariance matrix from data); float *phi, *lambda; // eigenvectors and eigenvalues int vecNum; // number of eigenvectors (<=n) phi = new float [n*vecNum]; lambda = new float [vecNum]; theMat.PCA( C, n, phi, lambda, vecNum ); delete phi; delete lambda; theMat.freeMat( C, n ); The matrix diagonalization function can also be applied to the computation of singular value decomposition (SVD), Fisher linear discriminant analysis (FLDA) and kernel PCA (KPCA) if forming the symmetric matrix appropriately. For data of very high dimensionality (n), the computation of nxn matrix is very expensive on personal computer. But if the number m of samples (vectors) is smaller than dimenionality, the problem can be converted to the computation of mxm matrix. The users are recommended to read the paper KPCA for how to form mxm matrix: B. Sch枚lkopf, A. Smola, K.-R. M眉ller. Nonlinear component analysis as a kernel eigenvalue problem, Neural Computation, 10(5): 1299-1319, 1998. Example ======= Refer to `example' directory for a simple demonstration.
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值