一个简单的矩阵类编写实例

http://www.cnblogs.com/JoeDZ/archive/2008/06/30/1232741.html

#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        


 
实现
#include<iostream.h>
#include<math.h>                
#include<stdlib.h>                
#include<iomanip.h>             
#include"matrix.h"

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

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

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

    for(int i=0; i<n; i++)
       this->mtx[i] = obj.getMtx()[i];                              
    return *this;
}   
           
// 负号操作符,返回值为该矩阵的负矩阵,原矩阵不变
Matrix Matrix::operator- ()const{                
    // 为了不改变原来的矩阵,此处从新构造一个矩阵
         Matrix _A(this->row, this->col);

    for(int i=0; i<_A.n; i++)
       _A.mtx[i] = -(this->mtx[i]);
    return _A;       
}                                                                                                  
// 矩阵求和,对应位置元素相加
Matrix operator+ (const Matrix &A, const Matrix &B){                
    Matrix AB(A.row, A.col);

    if(A.row!=B.row || A.col!=B.col){
       cout << "Can't do A+B\n"; // 如果矩阵A和B行列数不一致则不可相加
             exit(0);        
    }

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

    Matrix AB(A.row, B.col); // AB用于保存乘积

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

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

// 矩阵的转置 将(i,j)与(j,i)互换
// 此函数返回一个矩阵的转置矩阵,并不改变原来的矩阵
Matrix trv(const Matrix &A){
    Matrix AT(A.col, A.row);
    for(int i=0; i<AT.row; i++)
       for(int j=0; j<AT.col; j++)
          AT.set(i, j, A.get(j,i));
    return AT;       
}
                                                                                  
// 矩阵行列式值,采用列主元消去法
double det(Matrix A){
    if(A.row != A.col) {    // 矩阵必须为n*n的才可进行行列式求值       
        cout << "error" << endl;
        return 0.0;     //如果不满足行列数相等返回0.0    }

    double detValue = 1.0;  // 用于保存行列式值
    for(int i=0; i<A.getRow()-1; i++){ // 需要n-1步列化零操作

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


 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
下面是一个使用Hadoop编写矩阵乘法的示例: 1. 首先,需要创建一个输入矩阵A和一个输入矩阵B。这些矩阵可以存储在HDFS中,每行一个元素,使用逗号分隔。 2. 然后,我们需要编写一个MapReduce程序来执行矩阵乘法。Map函数将输入矩阵A的行作为键,列和值作为值,并将其传递给Reduce函数。Reduce函数将输入矩阵B的列作为键,行和值作为值,并将其与Map函数传递的值相乘。 3. 最后,我们需要运行MapReduce作业并将结果存储在HDFS中。结果将是一个输出矩阵C,其中每个元素都是A和B的相应元素乘积的总和。 以下是示例代码: ```java public class MatrixMultiplication { public static class Map extends Mapper<LongWritable, Text, Text, Text> { private Text outputKey = new Text(); private Text outputValue = new Text(); public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String[] matrixRow = value.toString().split(","); String matrixName = matrixRow[0]; String row = matrixRow[1]; String col = matrixRow[2]; String val = matrixRow[3]; if (matrixName.equals("A")) { for (int i = 0; i < 10; i++) { outputKey.set(row + "," + i); outputValue.set(matrixName + "," + col + "," + val); context.write(outputKey, outputValue); } } else { for (int i = 0; i < 10; i++) { outputKey.set(i + "," + col); outputValue.set(matrixName + "," + row + "," + val); context.write(outputKey, outputValue); } } } } public static class Reduce extends Reducer<Text, Text, Text, Text> { public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException { Map<String, Float> mapA = new HashMap<String, Float>(); Map<String, Float> mapB = new HashMap<String, Float>(); for (Text value : values) { String[] matrixRow = value.toString().split(","); String matrixName = matrixRow[0]; String row = matrixRow[1]; String col = matrixRow[2]; String val = matrixRow[3]; if (matrixName.equals("A")) { mapA.put(col, Float.parseFloat(val)); } else { mapB.put(row, Float.parseFloat(val)); } } float result = 0.0f; for (String col : mapA.keySet()) { if (mapB.containsKey(col)) { result += mapA.get(col) * mapB.get(col); } } String[] outputKeyArr = key.toString().split(","); String outputKey = outputKeyArr[0] + "," + outputKeyArr[1]; context.write(new Text(outputKey), new Text(Float.toString(result))); } } public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); Job job = Job.getInstance(conf, "matrix multiplication"); job.setJarByClass(MatrixMultiplication.class); job.setMapperClass(Map.class); job.setReducerClass(Reduce.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(Text.class); FileInputFormat.addInputPath(job, new Path(args[0])); FileOutputFormat.setOutputPath(job, new Path(args[1])); System.exit(job.waitForCompletion(true) ? 0 : 1); } } ``` 这个示例程序将输入矩阵A和矩阵B作为命令行参数传递,并将输出矩阵C存储在HDFS上的指定目录中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值