斯密特正交化进行QR分解

矩阵类:

#include<iostream>  
#include <stdlib.h>  
#include <math.h>    
#define iter 60   //迭代次数
using namespace std;  
class Matrix  
{  
public:  
	Matrix(const Matrix &rhs)//拷贝构造
	{
		if(this != &rhs) {
			row=rhs.row;
			col=rhs.col;
			size=row*col;
			pmm=new double[size];
			for(unsigned i=0; i<size; i++)
				pmm[i]=rhs.pmm[i];
		}
	}
	Matrix(unsigned r,unsigned c):row(r),col(c)//非方阵  
	{  
		size=r*c;  
		if (size>0)
		{
			pmm = new double[size];  
			for(unsigned int j=0;j<size;j++) //init  
			{  
				pmm[j]=0.0;  
			}  
		}
		else
			pmm=NULL;

	};  
	Matrix(unsigned n):row(n),col(n)//方阵  
	{  
		size=n*n;  
		if (size>0)
		{
			pmm = new double[size];  
			for(unsigned int j=0;j<size;j++) //init  
			{  
				pmm[j]=0.0;  
			}  
		}
		else
			pmm=NULL;
	};  
	~Matrix()
	{
		if (pmm!=NULL)  
		{    
			delete []pmm;  
		}  
	}  
	Matrix  &operator=(const Matrix& );  //赋值,必须是成员  
	friend istream &operator>>(istream&, Matrix&);  
	friend ostream &operator<<(ostream&, Matrix&);  
	friend Matrix  operator+(const Matrix&,const Matrix&);  
	friend Matrix  operator*(const Matrix&,const Matrix&);  
	double det();
	Matrix diag();  
	void sort();  	 
	void VectValue();  
	unsigned getrow(){return row;}
	unsigned getcolumn(){return col;}
	double MatrixNorm2();//2范数     
	double*operator[](int i)//a[i][j]直接访问元素
	{
		return pmm+i*row;
	}
private:
	unsigned  row,col,size ;    
	double *pmm;//数组指针  
	void QR(Matrix&,Matrix&)const;  
	void EigenVect(const Matrix& eigenValue ,Matrix &eigenVector);  
};  


//友元仅仅是指定了访问权限,不是一般意义的函数声明,最好在类外再进行一次函数声明。  
istream &operator>>(istream &is, Matrix &obj);  
ostream &operator<<(ostream &is, Matrix &obj);  
//对称性运算符,如算术,相等,应该是普通非成员函数。  
Matrix  operator*( const Matrix&,const Matrix& );  
Matrix  operator+( const Matrix&,const Matrix& );  
double dets(int n, double *&aa)
{
	double *bb = new double[(n-1)*(n-1)];//创建n-1阶的代数余子式阵bb 	
	int p=0,//判断行是否移动
		q=0;//代数余子式
	if(n == 1) 
	{
		return aa[0]; 
	}
	double sum=0.0;//sum为行列式的值
	for(int ai=0;ai<n;ai++) // a的行数把矩阵a(nn)赋值到b(n-1)
	{
		for(int bi=0;bi<n-1;bi++)//把元素aa[ai][0]代数余子式存到bb[][]
		{
			if(ai>bi)    //ai行的代数余子式是:小于ai的行,aa与bb阵,同行赋值
				p=0;
			else         
				p=1;     //大于等于ai的行,取aa阵的ai+1行赋值给阵bb的bi行
			for(int j=0;j<n-1;j++)  //从aa的第二列赋值到第n列
			{
				bb[bi*(n-1)+j]=aa[(bi+p)*n+j+1];
			}
		}
		if(ai%2==0)  q=1;//因为列数为0,所以行数是偶数时候,代数余子式为-1.
		else  q=(-1);
		sum+= q* aa[ai*n] *dets(n-1,bb);
	}
	return sum;
	delete []bb;
}

double Matrix::det()
{
	if(col==row)
	{
		 return dets(row,pmm) ;
	 
	}
	else
	{
		cout<<("行列不相等无法计算")<<endl;
		return 0;
	}
}
/  
istream &operator>>(istream &is, Matrix &obj)  
{  
	for (unsigned i=0; i<obj.size; i++)  
	{  
		is>>obj.pmm[i];  
	}  
	return is;  
}  
ostream &operator<<(ostream &out, Matrix &obj)  
{  
	for( unsigned i = 0; i < obj.row; i++) //打印逆矩阵    
	{    
		for( unsigned j = 0; j < obj.col; j++)     
		{       
			cout<< obj.pmm[i*obj.col+j]<<"\t";     
		}    
		cout<<endl;    
	}  
	return out;  
}  

Matrix operator+( const Matrix& lm,const Matrix& rm)  
{  
	Matrix ret(lm.row,lm.col);  
	for (unsigned i=0;i<ret.size;i++)  
	{  
		ret.pmm[i]=lm.pmm[i] + rm.pmm[i];  
	}  
	return ret;  
}  

Matrix operator*( const Matrix& lm,const Matrix& rm)    
{    
	if(lm.size==0||rm.size==0||lm.col != rm.row)  
	{     
		Matrix temp(0,0);  
		temp.pmm=NULL;
		return temp; //数据不合法时候,返回空矩阵  
	}  
	Matrix ret(lm.row, rm.col);    
	for( unsigned i=0;i<lm.row;i++)   
	{  
		for(unsigned j=0; j< rm.col;j++)  
		{  
			for(unsigned k=0; k< lm.col;k++)//lm.col == rm.row  
			{  
				ret.pmm[i*rm.col+j]+= lm.pmm[i*lm.col+k] * rm.pmm[k*rm.col+j];  
			}  
		}     
	}  
	return ret;  
}  

Matrix&  Matrix::operator=( const Matrix& B  )  
{  
	row=B.row;  
	col=B.col;  
	size=B.size;  
	for (unsigned i=0;i<size;i++)  
	{  
		pmm[i]=B.pmm[i];  
	}  
	return *this;  
}  
//||matrix||_2  求A矩阵的2范数    
double Matrix::MatrixNorm2()    
{      
	double norm = 0;    
	for(unsigned i = 0;i < size;++i)    
	{    
		norm += pmm[i] * pmm[i];    
	}    
	return (double)sqrt(norm);    
}    
void Matrix::sort()  
{  
	double tem;  
	for (unsigned i=0; i<size;i++)  
	{  
		for (unsigned j=i+1; j<size;j++)  
		{  
			if (pmm[i]<pmm[j])  
			{  
				tem=pmm[i];  
				pmm[i]=pmm[j];  
				pmm[j]=tem;  
			}  
		}  
	}  
}  

Matrix Matrix::diag()
{  
	if (row!=col)  
	{
		Matrix m(0);
		return m;
	}
	Matrix m(row,1);
	for (unsigned i=0;i<row;i++)  
	{  
		m.pmm[i]=pmm[i*row+i];  
	}  
	return m;  
}


//----------------------QR分解-------------------------------------------    

//将A分解为Q和R    
void  Matrix::QR(Matrix &Q,Matrix &R) const   
{    
	//如果A不是一个二维方阵,则提示错误,函数计算结束    
	if(row != col )    
	{    
		printf("ERROE: QR() parameter A is not a square matrix!\n");    
		return;    
	}   
	const unsigned N = row;    
	double *a=new double[N];  
	double *b=new double[N];  

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

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

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

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

		for(unsigned i = 0; i < N; ++i)    
		{    
			Q.pmm[i * N + j] = b[i] / norm; //Q 阵的第j列为单位化的b[]  
		}    
	}    
	delete[]a;  
	delete[]b;  
}    

//----------已知矩阵的特征值求矩阵特征向量-----------------    
//eigenValue为矩阵A的特征值,  
//eigenVector为计算结果即矩阵A的特征向量    
void Matrix::EigenVect(const Matrix& eigenValue ,Matrix &eigenVector)    
{    
	const unsigned NUM = col;    
	double eValue;    
	double sum,midSum,diag;    
	Matrix copym(*this);  
	for(unsigned count = 0; count < NUM;++count)    
	{    
		//计算特征值为eValue,求解特征向量时的系数矩阵   
		*this=copym;  
		eValue = eigenValue.pmm[count] ;    

		for(unsigned i = 0 ; i <  col ; ++i)//A-lambda*I   
		{    
			pmm[i * col + i] -= eValue;    
		}    
		//cout<<*this<<endl;  
		//将 this为阶梯型的上三角矩阵    
		for(unsigned i = 0 ; i <  row - 1 ; ++i)    
		{    
			diag =  pmm[i*col + i];  //提取对角元素
			for(unsigned j = i; j < col; ++j)    
			{
				pmm[i*col + j] /= diag; //【i,i】元素变为1
			}    
			for(unsigned j=i+1; j<row; ++j)    
			{    
				diag =  pmm[j *  col + i];    
				for(unsigned q = i ; q <  col; ++q)//消去第i+1行的第i个元素
				{    
					pmm[j*col + q] -= diag*pmm[i*col + q];    
				}    
			}    
		}    
		//cout<<*this<<endl;  
		//特征向量最后一行元素置为1
		midSum = eigenVector.pmm[(eigenVector.row - 1) * eigenVector.col + count] = 1;    
		for(int m =  row - 2; m >= 0; --m)    
		{    
			sum = 0;    
			for(unsigned j = m + 1;j <  col; ++j)    
			{    
				sum +=  pmm[m *  col + j] * eigenVector.pmm[j * eigenVector.col + count];    
			}    
			sum= -sum /  pmm[m *  col + m];    
			midSum +=  sum * sum;    
			eigenVector.pmm[m * eigenVector.col + count] = sum;    
		}    
		midSum = sqrt(midSum);    
		for(unsigned i = 0; i < eigenVector.row ; ++i)    
		{    
			eigenVector.pmm[i * eigenVector.col + count] /= midSum; //每次求出一个列向量  
		}    
	}    
}   

void Matrix::VectValue()  
{  
	if (size==0||row!=col)  
	{  
		cout<<"矩阵为空或者非方阵!"<<endl;  
		return;  
	}  
	if (det()==0)  
	{  
		cout<<"非满秩矩阵没法用QR分解计算特征值!"<<endl;  
		return;  
	}  
	const unsigned N=row;  
	Matrix A(*this);//备份矩阵  
	Matrix Q(N),R(N);  
	/*当迭代次数足够多时,A 趋于上三角矩阵,上三角矩阵的对角元就是A的全部特征值。*/  
	for(int k = 0;k < iter; ++k)    
	{  
		//cout<<"this:\n"<<*this<<endl;  
		QR(Q,R);  
		*this=R*Q;    
		/*	cout<<"Q:\n"<<Q<<endl;  
		cout<<"R:\n"<<R<<endl;  */
	}   

	Matrix eigenValue=diag();//特征值  
	cout<<"\neigenValue:\n"<<eigenValue<<endl;  

	Matrix eigenVect(N);//特征向量  
	A.EigenVect (eigenValue,eigenVect);    
	cout<<"\neigenVect:\n"<<eigenVect<<endl;  
  
}  

测试用的主函数:

#include"matrix.h"  
#include<iostream>  
#include <fstream>      // std::ifstream  
using namespace std;
 
int main()  
{  
	cout<<"输入阶数:";  
	int N=0;  
	cin>>N;  
	Matrix mm(N);  
	int flag=1;  
	cout<<"屏幕输入矩阵按0,其他数字则从文件mm.txt读入矩阵:";  
	cin>>flag;  
	cout<<endl;  
	if (flag==0)  
	{  
		cout<<"input matrix:"<<endl;  
		cin>>mm;  
	}else  
	{  
		ifstream ifs;  
		ifs.open ("mm.txt", ifstream::in);  
		ifs>>mm;  
	}  

	mm.VectValue();  
	system("pause");  
}  


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值