zoukankan      html  css  js  c++  java
  • 矩阵基本操作的实现(C# 源代码)

    第一次搬进自己的blog,打算放点东东到里面。在工程软件开发过程中,会碰到很多有关矩阵的运算。这是一年前的源代码

      1using System;
      2using System.IO;
      3using System.Diagnostics;
      4
      5
      6namespace Adjust
      7{
      8    /// <summary>
      9    /// Matrix 的摘要说明。
     10    /// 实现矩阵的基本运算
     11    /// </summary>

     12    public class Matrix
     13    {
     14    
     15        //构造方阵
     16        public  Matrix(int row)
     17        {
     18            m_data = new double[row,row];
     19
     20        }

     21        public Matrix(int row,int col)
     22        {
     23            m_data = new double[row,col];
     24        }

     25        //复制构造函数
     26        public Matrix(Matrix m)
     27        {
     28            int row = m.Row;
     29            int col = m.Col;
     30            m_data = new double[row,col];
     31
     32            for(int i=0;i<row;i++)
     33                for(int j=0;j<col;j++)
     34                    m_data[i,j] = m[i,j];
     35
     36        }

     37
     38        /*
     39        //分配方阵的大小
     40        //对于已含有内存的矩阵,将清空数据
     41        public void SetSize(int row)
     42        {
     43            m_data = new double[row,row];
     44        }
     45
     46        
     47        //分配矩阵的大小
     48        //对于已含有内存的矩阵,将清空数据
     49        public void SetSize(int row,int col)
     50        {
     51            m_data = new double[row,col];
     52        }
     53        */

     54
     55        //unit matrix:设为单位阵
     56        public void SetUnit()
     57        {
     58            for(int i=0;i<m_data.GetLength(0);i++)
     59                for(int j=0;j<m_data.GetLength(1);j++)
     60                    m_data[i,j] = ((i==j)?1:0);
     61        }

     62
     63        //设置元素值
     64        public void SetValue(double d)
     65        {
     66            for(int i=0;i<m_data.GetLength(0);i++)
     67                for(int j=0;j<m_data.GetLength(1);j++)
     68                    m_data[i,j] = d;
     69        }

     70
     71        // Value extraction:返中行数
     72        public int Row
     73        {
     74            get
     75            {
     76
     77                return m_data.GetLength(0);
     78            }

     79        }

     80
     81        //返回列数
     82        public int Col
     83        {
     84            get
     85            {
     86                return m_data.GetLength(1);
     87            }

     88        }

     89
     90        //重载索引
     91        //存取数据成员
     92        public double this[int row,int col]
     93        {
     94            get
     95            {
     96                return m_data[row,col];
     97            }

     98            set
     99            {
    100                m_data[row,col] = value;
    101            }

    102        }

    103
    104        //primary change
    105        // 初等变换 对调两行:ri<-->rj
    106        public Matrix  Exchange(int i,int j)
    107        {
    108            double temp;
    109
    110            for(int k=0;k<Col;k++)
    111            {
    112                temp = m_data[i,k];
    113                m_data[i,k] = m_data[j,k];
    114                m_data[j,k] = temp;
    115            }

    116            return this;
    117        }

    118
    119
    120        //初等变换 第index 行乘以mul
    121        Matrix Multiple(int index,double mul)    
    122        {
    123            for(int j=0;j<Col;j++)
    124            {
    125                m_data[index,j] *= mul;
    126            }

    127            return this;
    128        }

    129                
    130
    131        //初等变换 第src行乘以mul加到第index行
    132        Matrix MultipleAdd(int index,int src,double mul)
    133        {
    134            for(int j=0;j<Col;j++)
    135            {
    136                m_data[index,j] += m_data[src,j]*mul;
    137            }

    138
    139            return this;
    140        }

    141
    142        //transpose 转置
    143        public Matrix Transpose()
    144        {
    145            Matrix ret = new Matrix(Col,Row);
    146
    147            for(int i=0;i<Row;i++)
    148                for(int j=0;j<Col;j++)
    149                {
    150                    ret[j,i] = m_data[i,j];
    151                }

    152            return ret;
    153        }

    154        
    155        //binary addition 矩阵加
    156        public static Matrix operator+ (Matrix lhs,Matrix rhs)
    157        {
    158            if(lhs.Row != rhs.Row)    //异常
    159            {
    160                System.Exception e = new Exception("相加的两个矩阵的行数不等");
    161                throw e;
    162            }

    163            if(lhs.Col != rhs.Col)     //异常
    164            {
    165                System.Exception e = new Exception("相加的两个矩阵的列数不等");
    166                throw e;
    167            }

    168
    169            int row = lhs.Row;
    170            int col = lhs.Col;
    171            Matrix ret=new Matrix(row,col);
    172
    173            for(int i=0;i<row;i++)
    174                for(int j=0;j<col;j++)
    175                {
    176                    double d = lhs[i,j] + rhs[i,j];
    177                    ret[i,j] = d;
    178                }

    179            return ret;
    180
    181        }

    182
    183        //binary subtraction 矩阵减
    184        public static Matrix operator- (Matrix lhs,Matrix rhs)
    185        {
    186            if(lhs.Row != rhs.Row)    //异常
    187            {
    188                System.Exception e = new Exception("相减的两个矩阵的行数不等");
    189                throw e;
    190            }

    191            if(lhs.Col != rhs.Col)     //异常
    192            {
    193                System.Exception e = new Exception("相减的两个矩阵的列数不等");
    194                throw e;
    195            }

    196
    197            int row = lhs.Row;
    198            int col = lhs.Col;
    199            Matrix ret=new Matrix(row,col);
    200
    201            for(int i=0;i<row;i++)
    202                for(int j=0;j<col;j++)
    203                {
    204                    double d = lhs[i,j] - rhs[i,j];
    205                    ret[i,j] = d;
    206                }

    207            return ret;
    208        }

    209
    210
    211        //binary multiple 矩阵乘
    212        public static Matrix operator* (Matrix lhs,Matrix rhs)
    213        {
    214            if(lhs.Col != rhs.Row)    //异常
    215            {
    216                System.Exception e = new Exception("相乘的两个矩阵的行列数不匹配");
    217                throw e;
    218            }

    219
    220            Matrix ret = new Matrix (lhs.Row,rhs.Col);
    221            double temp;
    222            for(int i=0;i<lhs.Row;i++)
    223            {
    224                for(int j=0;j<rhs.Col;j++)
    225                {
    226                    temp = 0;
    227                    for(int k=0;k<lhs.Col;k++)
    228                    {
    229                        temp += lhs[i,k] * rhs[k,j];
    230                    }

    231                    ret[i,j] = temp;
    232                }

    233            }

    234
    235            return ret;
    236        }

    237
    238
    239        //binary division 矩阵除
    240        public static Matrix operator/ (Matrix lhs,Matrix rhs)
    241        {
    242            return lhs * rhs.Inverse();
    243        }

    244
    245        //unary addition单目加
    246        public static Matrix operator+ (Matrix m)
    247        {
    248            Matrix ret = new Matrix(m);
    249            return ret;
    250        }

    251
    252        //unary subtraction 单目减
    253        public static Matrix operator- (Matrix m)
    254        {
    255            Matrix ret = new Matrix(m);
    256            for(int i=0;i<ret.Row;i++)
    257                for(int j= 0;j<ret.Col;j++)
    258                {
    259                    ret[i,j] = -ret[i,j];
    260                }

    261
    262            return ret;
    263        }

    264
    265        //number multiple 数乘
    266        public static Matrix operator* (double d,Matrix m)
    267        {
    268            Matrix ret = new Matrix(m);
    269            for(int i=0;i<ret.Row;i++)
    270                for(int j=0;j<ret.Col;j++)
    271                    ret[i,j] *= d;
    272
    273            return ret;
    274        }

    275
    276        //number division 数除
    277        public static Matrix operator/ (double d,Matrix m)
    278        {
    279            return d*m.Inverse();
    280        }

    281
    282        //功能:返回列主元素的行号
    283        //参数:row为开始查找的行号
    284        //说明:在行号[row,Col)范围内查找第row列中绝对值最大的元素,返回所在行号
    285        int Pivot(int row)
    286        {
    287            int index=row;
    288
    289            for(int i=row+1;i<Row;i++)
    290            {
    291                if(m_data[i,row] > m_data[index,row])
    292                    index=i;
    293            }

    294
    295            return index;
    296        }

    297
    298        //inversion 逆阵:使用矩阵的初等变换,列主元素消去法
    299        public Matrix Inverse()
    300        {
    301            if(Row != Col)    //异常,非方阵
    302            {
    303                System.Exception e = new Exception("求逆的矩阵不是方阵");
    304                throw e;
    305            }

    306StreamWriter sw = new StreamWriter("..\\annex\\close_matrix.txt");
    307            Matrix tmp = new Matrix(this);
    308            Matrix ret =new Matrix(Row);    //单位阵
    309            ret.SetUnit();
    310
    311            int maxIndex;
    312            double dMul;
    313
    314            for(int i=0;i<Row;i++)
    315            {
    316                maxIndex = tmp.Pivot(i);
    317    
    318                if(tmp.m_data[maxIndex,i]==0)
    319                {
    320                    System.Exception e = new Exception("求逆的矩阵的行列式的值等于0,");
    321                    throw e;
    322                }

    323
    324                if(maxIndex != i)    //下三角阵中此列的最大值不在当前行,交换
    325                {
    326                    tmp.Exchange(i,maxIndex);
    327                    ret.Exchange(i,maxIndex);
    328
    329                }

    330
    331                ret.Multiple(i,1/tmp[i,i]);
    332
    333                tmp.Multiple(i,1/tmp[i,i]);
    334
    335                for(int j=i+1;j<Row;j++)
    336                {
    337                    dMul = -tmp[j,i]/tmp[i,i];
    338                    tmp.MultipleAdd(j,i,dMul);
    339                    ret.MultipleAdd(j,i,dMul);
    340    
    341                }

    342sw.WriteLine("tmp=\r\n"+tmp);
    343sw.WriteLine("ret=\r\n"+ret);
    344            }
    //end for
    345
    346
    347sw.WriteLine("**=\r\n"+ this*ret);
    348
    349            for(int i=Row-1;i>0;i--)
    350            {
    351                for(int j=i-1;j>=0;j--)
    352                {
    353                    dMul = -tmp[j,i]/tmp[i,i];
    354                    tmp.MultipleAdd(j,i,dMul);
    355                    ret.MultipleAdd(j,i,dMul);
    356                }

    357            }
    //end for
    358
    359
    360sw.WriteLine("tmp=\r\n"+tmp);
    361sw.WriteLine("ret=\r\n"+ret);
    362sw.WriteLine("***=\r\n"+ this*ret);
    363sw.Close();
    364        
    365            return ret;
    366
    367        }
    //end Inverse
    368
    369        #region
    370/*
    371        //inversion 逆阵:使用矩阵的初等变换,列主元素消去法
    372        public Matrix Inverse()
    373        {
    374            if(Row != Col)    //异常,非方阵
    375            {
    376                System.Exception e = new Exception("求逆的矩阵不是方阵");
    377                throw e;
    378            }
    379            ///////////////
    380            StreamWriter sw = new StreamWriter("..\\annex\\matrix_mul.txt");
    381            ////////////////////
    382            ///    
    383            Matrix tmp = new Matrix(this);
    384            Matrix ret =new Matrix(Row);    //单位阵
    385            ret.SetUnit();
    386
    387            int maxIndex;
    388            double dMul;
    389
    390            for(int i=0;i<Row;i++)
    391            {
    392
    393                maxIndex = tmp.Pivot(i);
    394    
    395                if(tmp.m_data[maxIndex,i]==0)
    396                {
    397                    System.Exception e = new Exception("求逆的矩阵的行列式的值等于0,");
    398                    throw e;
    399                }
    400
    401                if(maxIndex != i)    //下三角阵中此列的最大值不在当前行,交换
    402                {
    403                    tmp.Exchange(i,maxIndex);
    404                    ret.Exchange(i,maxIndex);
    405
    406                }
    407
    408                ret.Multiple(i,1/tmp[i,i]);
    409
    410                /////////////////////////
    411                //sw.WriteLine("nul \t"+tmp[i,i]+"\t"+ret[i,i]);
    412                ////////////////
    413                tmp.Multiple(i,1/tmp[i,i]);
    414                //sw.WriteLine("mmm \t"+tmp[i,i]+"\t"+ret[i,i]);
    415                sw.WriteLine("111111111 tmp=\r\n"+tmp);
    416                for(int j=i+1;j<Row;j++)
    417                {
    418                    dMul = -tmp[j,i];
    419                    tmp.MultipleAdd(j,i,dMul);
    420                    ret.MultipleAdd(j,i,dMul);
    421    
    422                }
    423                sw.WriteLine("222222222222=\r\n"+tmp);
    424
    425            }//end for
    426
    427
    428
    429            for(int i=Row-1;i>0;i--)
    430            {
    431                for(int j=i-1;j>=0;j--)
    432                {
    433                    dMul = -tmp[j,i];
    434                    tmp.MultipleAdd(j,i,dMul);
    435                    ret.MultipleAdd(j,i,dMul);
    436                }
    437            }//end for
    438        
    439            //////////////////////////
    440
    441
    442            sw.WriteLine("tmp = \r\n" + tmp.ToString());
    443
    444            sw.Close();
    445            ///////////////////////////////////////
    446            ///
    447            return ret;
    448
    449        }//end Inverse
    450
    451*/

    452
    453        #endregion

    454
    455        //determine if the matrix is square:方阵
    456        public bool IsSquare()
    457        {
    458            return Row==Col;
    459        }

    460
    461        //determine if the matrix is symmetric对称阵
    462        public bool IsSymmetric()
    463        {
    464
    465            if(Row != Col) 
    466                return false;
    467                             
    468            for(int i=0;i<Row;i++)
    469                for(int j=i+1;j<Col;j++)
    470                    if( m_data[i,j] != m_data[j,i])
    471                        return false;
    472
    473            return true;
    474        }

    475
    476        //一阶矩阵->实数
    477        public double ToDouble()
    478        {
    479            Trace.Assert(Row==1 && Col==1);
    480
    481            return m_data[0,0];
    482        }

    483
    484        //conert to string
    485        public override string ToString()
    486        {
    487        
    488            string s="";
    489            for(int i=0;i<Row;i++)
    490            {
    491                for(int j=0;j<Col;j++)
    492                    s += string.Format("{0} ",m_data[i,j]);
    493
    494                s += "\r\n";
    495            }

    496            return s;
    497
    498        }

    499
    500
    501        //私有数据成员
    502        private double[,] m_data;
    503        
    504    }
    //end class Matrix
    505}
    上面的矩阵类,用起来很方便。

    例子:

    //Square n*n Matrix 
    Matrix m1 = new Matrix(n);
    //m*n Matrix
    Matrix m2 = new Matrix(m,n):
    //Matrix Add Operattion
    Mtrix result = m_1 + m_2;
    //Display Matrix Method 1
    for(int i=0;i<m.Row;i++)
      
    {
        
    for(int j=0;j<m.Col;j++)
          Console.WriteLine(m[i,j]);
        Console.Writeline();
       }

    //Display Matrix Method 2
    Console.WriteLine(m.ToString()); 
    说明:类实现了矩阵的所有基本操作,包括单双目的+,-,×、/(Inversion),初等变换(三种数学上的初等变换),还有很多,希望读者自己体会。另有标准C++源代码,实现了上面的所有的功能。
  • 相关阅读:
    xml序列化
    C#.NET对象深拷贝
    C++的函数传参
    hubilder热更新
    qrcode加背景图
    js点击屏幕出现文字
    JS实现搜索匹配功能
    FiraCode字体(好看的字体)
    基于PHP和JS的AES相互加密解密方法详解(CryptoJS)
    常见的正则匹配
  • 原文地址:https://www.cnblogs.com/xiexiaokui/p/157657.html
Copyright © 2011-2022 走看看