矩阵计算程序

#ifndef _MATRIX_H
#define  _MATRIX_H

class  Matrix
{
    
private :
       
int      row;     //  矩阵的行数
         int      col;     //  矩阵的列数
         int      n;       //  矩阵元素个数
         double *     mtx;  //  动态分配用来存放数组的空间
     public :
        Matrix(
int  row = 1 int  col = 1 );              //  带默认参数的构造函数
        Matrix( int  row,  int  col,  double  mtx[]);     //  用数组创建一个矩阵
        Matrix( const  Matrix  & obj);                  //  copy构造函数
        ~ Matrix() { delete[]  this -> mtx; }        

        
void     print() const ;                      //  格式化输出矩阵
         int      getRow() const  {  return   this -> row; } //  访问矩阵行数
         int      getCol() const  {  return   this -> col; } //  访问矩阵列数
         int      getN() const    {  return   this -> n;   } //  访问矩阵元素个数
         double *  getMtx() const  {  return   this -> mtx; } //  获取该矩阵的数组
        
        
//  用下标访问矩阵元素
         double       get ( const   int  i,  const   int  j) const
        
//  用下标修改矩阵元素值
         void       set ( const   int  i,  const   int  j,  const   double  e); 

        
//  重载了一些常用操作符,包括 +,-,x,=,负号,正号,
        
//  A = B
        Matrix  & operator =  ( const  Matrix  & obj);
        
//  +A
        Matrix   operator +  () const  {  return   * this ; }
        
//  -A
        Matrix   operator -  () const ;
        
//  A + B
        friend  Matrix   operator +  ( const  Matrix  & A,  const  Matrix  & B);
        
//  A - B
        friend  Matrix   operator -  ( const  Matrix  & A,  const  Matrix  & B);
        
//  A * B 两矩阵相乘
        friend  Matrix   operator *  ( const  Matrix  & A,  const  Matrix  & B);
        
//  a * B 实数与矩阵相乘
        friend  Matrix   operator *  ( const   double   & a,  const  Matrix  & B);
        
//  A 的转置
        friend  Matrix  trv( const  Matrix  & A);
        
//  A 的行列式值,采用列主元消去法
        
//  求行列式须将矩阵化为三角阵,此处为了防止修改原矩阵,采用传值调用
        friend   double   det(Matrix A);
        
//  A 的逆矩阵,采用高斯-若当列主元消去法
        friend  Matrix  inv(Matrix A);
};
#endif         

None.gif 实现
None.gif#include
< iostream.h >
None.gif#include
< math.h >                 
None.gif#include
< stdlib.h >                 
None.gif#include
< iomanip.h >              
None.gif#include
" matrix.h "
None.gif
None.gif
//  带默认参数值的构造函数
None.gif
//  构造一个row行col列的零矩阵
ExpandedBlockStart.gifContractedBlock.gif
Matrix::Matrix( int  row,  int  col) dot.gif {                
InBlock.gif    
this->row = row;
InBlock.gif        
this->col = col;                                                         
InBlock.gif    
this->n   = row * col;
InBlock.gif        
this->mtx = new double[n];
InBlock.gif                                               
InBlock.gif    
for(int i=0; i<n; i++)
InBlock.gif           
this->mtx[i] = 0.0;
ExpandedBlockEnd.gif        }
                                                                                    
None.gif
//  用一个数组初始化矩阵                                                        
None.gif
Matrix::Matrix( int  row,  int  col,  double  mtx[])                                  
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
this->row = row;
InBlock.gif        
this->col = col;                                                         
InBlock.gif    
this->n   = row * col;    
InBlock.gif        
this->mtx = new double[n];                                               
InBlock.gif    
InBlock.gif        
for(int i=0; i<n; i++)                                                     
InBlock.gif       
this->mtx[i] = mtx[i];                                                
ExpandedBlockEnd.gif}
                                                                                                  
None.gif
//  拷贝构造函数,因为成员变量含有动态空间,防止传递参数 
None.gif
//  等操作发生错误
ExpandedBlockStart.gifContractedBlock.gif
Matrix::Matrix( const  Matrix  & obj) dot.gif {            
InBlock.gif    
this->row = obj.getRow();                                         
InBlock.gif    
this->col = obj.getCol();                                          
InBlock.gif    
this->n      = obj.getN();                                            
InBlock.gif    
this->mtx = new double[n];
InBlock.gif                                            
InBlock.gif    
for(int i=0; i<n; i++)
InBlock.gif       
this->mtx[i] = obj.getMtx()[i];
ExpandedBlockEnd.gif}
                                                                                                   
None.gif
//  格式化输出矩阵所有元素
ExpandedBlockStart.gifContractedBlock.gif
void  Matrix::print() const dot.gif {                
ExpandedSubBlockStart.gifContractedSubBlock.gif    
for(int i=0; i<this->row; i++)dot.gif{                                         
InBlock.gif       
for(int j=0; j<this->col; j++)
InBlock.gif          
if(fabs(this->get(i,j)) <= 1.0e-10)
InBlock.gif                cout 
<< setiosflags(ios::left) << setw(12<< 0.0 << ' ';
InBlock.gif              
else
InBlock.gif                cout 
<< setiosflags(ios::left) 
InBlock.gif                     
<< setw(12<< this->get(i,j) << ' ';
InBlock.gif           cout 
<<endl;      
ExpandedSubBlockEnd.gif    }
          
ExpandedBlockEnd.gif}

None.gif
None.gif
//  获取矩阵元素
None.gif
//  注意这里矩阵下标从(0,0)开始
ExpandedBlockStart.gifContractedBlock.gif
double  Matrix:: get ( const   int  i,  const   int  j) const dot.gif {                
InBlock.gif    
return this->mtx[i*this->col + j];                           
ExpandedBlockEnd.gif}

None.gif
None.gif
//  修改矩阵元素
ExpandedBlockStart.gifContractedBlock.gif
void  Matrix:: set ( const   int  i,  const   int  j,  const   double  e) dot.gif {                
InBlock.gif    
this->mtx[i*this->col + j] = e;                               
ExpandedBlockEnd.gif}
                                                            
None.gif                
None.gif
//  重载赋值操作符,由于成员变量中含有动态分配
ExpandedBlockStart.gifContractedBlock.gif
Matrix  & Matrix:: operator =  ( const  Matrix  & obj) dot.gif {                
InBlock.gif    
if(this == &obj)    // 将一个矩阵赋给它自己时简单做返回即可        
InBlock.gif
       return *this;
InBlock.gif    delete[] 
this->mtx; // 首先删除目的操作数的动态空间
InBlock.gif
    this->row = obj.getRow();
InBlock.gif    
this->col = obj.getCol();
InBlock.gif    
this->n   = obj.getN();
InBlock.gif    
this->mtx = new double[n]; // 重新分配空间保存obj的数组
InBlock.gif

InBlock.gif    
for(int i=0; i<n; i++)
InBlock.gif       
this->mtx[i] = obj.getMtx()[i];                              
InBlock.gif    
return *this;
ExpandedBlockEnd.gif}
   
None.gif           
None.gif
//  负号操作符,返回值为该矩阵的负矩阵,原矩阵不变
ExpandedBlockStart.gifContractedBlock.gif
Matrix Matrix:: operator -  () const dot.gif {                
InBlock.gif    
// 为了不改变原来的矩阵,此处从新构造一个矩阵
InBlock.gif
         Matrix _A(this->row, this->col);
InBlock.gif
InBlock.gif    
for(int i=0; i<_A.n; i++)
InBlock.gif       _A.mtx[i] 
= -(this->mtx[i]);
InBlock.gif    
return _A;       
ExpandedBlockEnd.gif}
                                                                                                  
None.gif
//  矩阵求和,对应位置元素相加
ExpandedBlockStart.gifContractedBlock.gif
Matrix  operator +  ( const  Matrix  & A,  const  Matrix  & B) dot.gif {                
InBlock.gif    Matrix AB(A.row, A.col);
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
if(A.row!=B.row || A.col!=B.col)dot.gif{
InBlock.gif       cout 
<< "Can't do A+B\n"// 如果矩阵A和B行列数不一致则不可相加
InBlock.gif
             exit(0);        
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
for(int i=0; i<AB.n; i++)
InBlock.gif       AB.mtx[i] 
= A.mtx[i] + B.mtx[i];
InBlock.gif    
InBlock.gif        
return AB;       
ExpandedBlockEnd.gif}
                                                                                                  
None.gif
//  矩阵减法,用加上一个负矩阵来实现
ExpandedBlockStart.gifContractedBlock.gif
Matrix  operator -  ( const  Matrix  & A,  const  Matrix  & B) dot.gif {                
InBlock.gif    
return (A + (-B));
ExpandedBlockEnd.gif}
                                                                                                  
None.gif
//  矩阵乘法
ExpandedBlockStart.gifContractedBlock.gif
Matrix  operator *  ( const  Matrix  & A,  const  Matrix  & B) dot.gif {                
ExpandedSubBlockStart.gifContractedSubBlock.gif    
if(A.col != B.row)dot.gif{    // A的列数必须和B的行数一致
InBlock.gif
       cout << "Can't multiply\n";
InBlock.gif       exit(
0);          
ExpandedSubBlockEnd.gif    }
                                                                          
InBlock.gif
InBlock.gif    Matrix AB(A.row, B.col); 
// AB用于保存乘积
InBlock.gif

InBlock.gif    
for(int i=0; i<AB.row; i++)
InBlock.gif       
for(int j=0; j<AB.col; j++)
InBlock.gif          
for(int k=0; k<A.col; k++)
InBlock.gif        AB.
set(i, j, AB.get(i,j) + A.get(i,k)*B.get(k,j));
InBlock.gif          
return AB;       
ExpandedBlockEnd.gif}

None.gif
None.gif
//  矩阵与实数相乘
ExpandedBlockStart.gifContractedBlock.gif
Matrix  operator *  ( const   double   & a,  const  Matrix  & B) dot.gif {
InBlock.gif    Matrix aB(B);
InBlock.gif    
for(int i=0; i<aB.row; i++)
InBlock.gif       
for(int j=0; j<aB.col; j++)
InBlock.gif          aB.
set(i,j, a*B.get(i,j));    
InBlock.gif    
return aB;
ExpandedBlockEnd.gif}

None.gif
None.gif
//  矩阵的转置 将(i,j)与(j,i)互换
None.gif
//  此函数返回一个矩阵的转置矩阵,并不改变原来的矩阵
ExpandedBlockStart.gifContractedBlock.gif
Matrix trv( const  Matrix  & A) dot.gif {
InBlock.gif    Matrix AT(A.col, A.row);
InBlock.gif    
for(int i=0; i<AT.row; i++)
InBlock.gif       
for(int j=0; j<AT.col; j++)
InBlock.gif          AT.
set(i, j, A.get(j,i));
InBlock.gif    
return AT;       
ExpandedBlockEnd.gif}

None.gif                                                                                  
None.gif
//  矩阵行列式值,采用列主元消去法
ExpandedBlockStart.gifContractedBlock.gif
double  det(Matrix A) dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
if(A.row != A.col) dot.gif{    // 矩阵必须为n*n的才可进行行列式求值       
InBlock.gif
        cout << "error" << endl;
InBlock.gif        
return 0.0;     //如果不满足行列数相等返回0.0    }
InBlock.gif

InBlock.gif    
double detValue = 1.0;  // 用于保存行列式值
ExpandedSubBlockStart.gifContractedSubBlock.gif
    for(int i=0; i<A.getRow()-1; i++)dot.gif// 需要n-1步列化零操作
InBlock.gif
InBlock.gif         
//------------------ 选主元 ---------------------------------    
InBlock.gif
       double max = fabs(A.get(i,i));    // 主元初始默认为右下方矩阵首个元素     
InBlock.gif
        int    ind = i;  
InBlock.gif          
// 主元行号默认为右下方矩阵首行      
InBlock.gif
    
ExpandedSubBlockStart.gifContractedSubBlock.gif       
for(int j=i+1; j<A.getRow(); j++)dot.gif{  // 选择列主元
ExpandedSubBlockStart.gifContractedSubBlock.gif
        if(fabs(A.get(j,i)) > max)dot.gif{     // 遇到绝对值更大的元素
InBlock.gif
           max = fabs(A.get(j,i));      // 更新主元值
InBlock.gif
           ind = j;                       // 更新主元行号
ExpandedSubBlockEnd.gif
        }
                  
ExpandedSubBlockEnd.gif      }
//loop j    
InBlock.gif    
InBlock.gif       
//------------------- 移动主元行 -----------------------------
InBlock.gif
       if(max <= 1.0e-10return 0.0;    // 右下方矩阵首行为零,显然行列式值为零      
ExpandedSubBlockStart.gifContractedSubBlock.gif
        if(ind != i)dot.gif{// 主元行非右下方矩阵首行                                  
ExpandedSubBlockStart.gifContractedSubBlock.gif
         for(int k=i; k<A.getRow(); k++)dot.gif{     // 将主元行与右下方矩阵首行互换          
InBlock.gif
         double temp = A.get(i,k);
InBlock.gif        A.
set(i,k,A.get(ind,k));
InBlock.gif        A.
set(ind,k,temp);
ExpandedSubBlockEnd.gif        }

InBlock.gif          detValue 
= -detValue;             // 互换行列式两行,行列式值反号    
ExpandedSubBlockEnd.gif
    }
                            
InBlock.gif    
InBlock.gif       
//------------------- 消元 ----------------------------------                                  
ExpandedSubBlockStart.gifContractedSubBlock.gif
        for(j=i+1; j<A.getRow(); j++)dot.gif{     // 遍历行  
InBlock.gif
            double temp = A.get(j,i)/A.get(i,i);        
InBlock.gif           
for(int k=i; k<A.getRow(); k++// 遍历行中每个元素,行首置0
ExpandedSubBlockEnd.gif
              A.set(j, k, A.get(j,k)-A.get(i,k)*temp);        }
                    
InBlock.gif          detValue 
*= A.get(i,i); // 每步消元都会产生一个对角线上元素,将其累乘
ExpandedSubBlockEnd.gif
       }
// loop i     
InBlock.gif      
InBlock.gif      
// 注意矩阵最后一个元素在消元的过程中没有被累乘到
ExpandedSubBlockEnd.gif
      return detValue * A.get(A.getRow()-1, A.getRow()-1);}
//det()        
InBlock.gif                                  
InBlock.gif      
// A的逆矩阵 高斯-若当消去法,按列选主元
ExpandedSubBlockStart.gifContractedSubBlock.gif
      Matrix inv(Matrix A)dot.gif{                
ExpandedSubBlockStart.gifContractedSubBlock.gif    
if(A.row != A.col)dot.gif// 只可求狭义逆矩阵,即行列数相同
InBlock.gif
       cout << "Matrix should be N x N\n";
InBlock.gif       exit(
0);       
ExpandedSubBlockEnd.gif    }
                                                                                                
InBlock.gif    
// 构造一个与A行列相同的单位阵B
InBlock.gif
    Matrix B(A.row,A.col);
InBlock.gif      
InBlock.gif    
for(int r=0; r<A.row; r++)
InBlock.gif       
for(int c=0; c<A.col; c++)
InBlock.gif          
if(r == c) B.set(r,c,1.0); 
InBlock.gif     
InBlock.gif    
// 对矩阵A进行A.row次消元运算,每次保证第K列只有对角线上非零
InBlock.gif    
// 同时以同样的操作施与矩阵B,结果A变为单位阵B为所求逆阵
ExpandedSubBlockStart.gifContractedSubBlock.gif
    for(int k=0; k<A.row; k++)dot.gif{
InBlock.gif    
//------------------ 选主元 --------------------------------------    
InBlock.gif
      double max = fabs(A.get(k,k));    // 主元初始默认为右下方矩阵首个元素     
InBlock.gif
     int    ind = k;            // 主元行号默认为右下方矩阵首行
InBlock.gif           
// 结果第ind行为列主元行
ExpandedSubBlockStart.gifContractedSubBlock.gif
      for(int n=k+1; n<A.getRow(); n++)dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif         
if(fabs(A.get(n,k)) > max)dot.gif{// 遇到绝对值更大的元素             
InBlock.gif
        max = fabs(A.get(n,k));    // 更新主元值
InBlock.gif
                  ind = n;// 更新主元行号
ExpandedSubBlockEnd.gif
      }

ExpandedSubBlockEnd.gif       }
                   
InBlock.gif       
//------------------- 移动主元行 --------------------------------
ExpandedSubBlockStart.gifContractedSubBlock.gif
       if(ind != k)dot.gif{// 主元行不是右下方矩阵首行
ExpandedSubBlockStart.gifContractedSubBlock.gif
           for(int m=k; m<A.row; m++)dot.gif{// 将主元行与右下方矩阵首行互换         
InBlock.gif
         double tempa = A.get(k,m);
InBlock.gif         A.
set(k, m, A.get(ind,m));
InBlock.gif             A.
set(ind, m, tempa);            
ExpandedSubBlockEnd.gif          }

ExpandedSubBlockStart.gifContractedSubBlock.gif      
for(m=0; m<B.row; m++)dot.gif{
InBlock.gif             
double tempb = B.get(k,m); // 对矩阵B施以相同操作                  
InBlock.gif
   B.set(k, m, B.get(ind,m)); // B与A阶数相同,可在一个循环中               
InBlock.gif
  B.set(ind, m, tempb);    
ExpandedSubBlockEnd.gif          }
    
ExpandedSubBlockEnd.gif       }
        
InBlock.gif      
//--------------------- 消元 -----------------------------------
InBlock.gif      
// 第k次消元操作,以第k行作为主元行,将其上下各行的第k列元素化为零
InBlock.gif       
// 同时以同样的参数对B施以同样的操作,此时可以将B看作A矩阵的一部分          
ExpandedSubBlockStart.gifContractedSubBlock.gif
      for(int i=0; i<A.col; i++)dot.gif{                                 
ExpandedSubBlockStart.gifContractedSubBlock.gif         
if(i != k)dot.gif{
InBlock.gif          
double Mik = -A.get(i,k)/A.get(k,k);                         
InBlock.gif          
for(int j=k+1; j<A.row; j++)
InBlock.gif                A.
set(i, j, A.get(i,j) + Mik*A.get(k,j));                     
InBlock.gif          
for(j=0; j<B.row; j++)
InBlock.gif                B.
set(i, j, B.get(i,j) + Mik*B.get(k,j));                   
ExpandedSubBlockEnd.gif        }
//end if 
ExpandedSubBlockEnd.gif
      }
//loop i  
InBlock.gif
      double Mkk = 1.0/A.get(k,k);
InBlock.gif      
InBlock.gif      
for(int j=0; j<A.row; j++)
InBlock.gif         A.
set(k, j, A.get(k,j) * Mkk);
InBlock.gif      
for(j=0; j<B.row; j++)
InBlock.gif         B.
set(k, j, B.get(k,j) * Mkk);
ExpandedSubBlockEnd.gif     }
//loop k      
InBlock.gif
     return B;
ExpandedBlockEnd.gif}
//inv()

转载于:https://www.cnblogs.com/JoeDZ/archive/2008/06/30/1232741.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值