数学(《线性代数》矩阵乘积|数学:《线性代数》矩阵乘积 之 代码实现)

背景 执行坐标变换的一工具就是使用矩阵乘法,这里给出矩阵乘法的简单实现。
矩阵乘法 核心代码

1public Matrix Multiply(Matrix matrix) 2{ 3if (this._n != matrix._m) 4{ 5throw new InvalidOperationException("左侧矩阵的列不等于右侧矩阵的行"); 6} 7 8var resultMatrix = new Matrix(this._m, matrix._n); 9 10for (var i = 0; i < resultMatrix._m; i++) 11{ 12for (var j = 0; j < resultMatrix._n; j++) 13{ 14resultMatrix._data[i][j] = Enumerable.Range(0, this._n).Sum(k => this._data[i][k] * matrix._data[k][j]); 15} 16} 17 18return resultMatrix; 19}

全部代码
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DataStuctureStudy.Matrixes 8 { 9class MatrixTest 10{ 11public static void Test() 12{ 13var matrixA = 14new Matrix(3, 3) 15.SetRowData(0, 1, 2, 3) 16.SetRowData(1, 1, 2, 7) 17.SetRowData(2, 4, 9, 2); 18 19var matrixB = matrixA.Simplify(); 20var matrixC = matrixA.Inverse(); 21 22matrixA.Dispaly(); 23matrixB.Dispaly(); 24matrixC.Dispaly(); 25matrixA.Multiply(matrixC).Dispaly(); 26 27} 28class Matrix 29{ 30private readonly int _m; 31private readonly int _n; 32private readonly double[][] _data; 33 34public Matrix(int m, int n) 35{ 36_m = m; 37_n = n; 38_data = https://www.it610.com/article/new double[m][]; 39for (var i = 0; i < m; i++) 40{ 41_data[i] = new double[n]; 42} 43} 44 45public Matrix SetRowData(int row, params double[] values) 46{ 47Array.Copy(values, _data[row], _n); 48 49return this; 50} 51 52public Matrix SwapRow(int rowX, int rowY) 53{ 54var resultMatrix = this.ConeSelf(); 55 56var temp = resultMatrix._data[rowX]; 57resultMatrix._data[rowX] = resultMatrix._data[rowY]; 58resultMatrix._data[rowY] = temp; 59 60return resultMatrix; 61} 62 63public Matrix MultiplyRow(int row, double operand) 64{ 65var resultMatrix = this.ConeSelf(); 66 67for (var i = 0; i < resultMatrix._n; i++) 68{ 69resultMatrix._data[row][i] *= operand; 70} 71 72return resultMatrix; 73} 74 75 76public Matrix AddSourceRowToTargetRow(int sourceRow, double operand, int targetRow) 77{ 78var resultMatrix = this.ConeSelf(); 79 80for (var i = 0; i < resultMatrix._n; i++) 81{ 82resultMatrix._data[targetRow][i] += resultMatrix._data[sourceRow][i] * operand; 83} 84 85return resultMatrix; 86} 87 88public Matrix Simplify() 89{ 90var resultMatrix = this.ConeSelf(); 91 92for (var col = 0; col < resultMatrix._n; col++) 93{ 94if (col>= _m) 95{ 96break; 97} 98 99if (resultMatrix._data[col][col] == 0) 100{ 101var nonZeroRowIndex = resultMatrix.FindNonZeroRowIndex(col, col + 1); 102if (nonZeroRowIndex == -1) 103{ 104break; 105} 106resultMatrix = resultMatrix.SwapRow(col, nonZeroRowIndex); 107} 108 109resultMatrix = resultMatrix.MultiplyRow(col, 1 / resultMatrix._data[col][col]); 110 111for (var row = 0; row < _m; row++) 112{ 113if (row == col) 114{ 115continue; 116} 117resultMatrix = resultMatrix.AddSourceRowToTargetRow(col, -1 * resultMatrix._data[row][col], row); 118} 119} 120 121return resultMatrix; 122} 123 124public Matrix Multiply(Matrix matrix) 125{ 126if (this._n != matrix._m) 127{ 128throw new InvalidOperationException("左侧矩阵的列不等于右侧矩阵的行"); 129} 130 131var resultMatrix = new Matrix(this._m, matrix._n); 132 133for (var i = 0; i < resultMatrix._m; i++) 134{ 135for (var j = 0; j < resultMatrix._n; j++) 136{ 137resultMatrix._data[i][j] = Enumerable.Range(0, this._n).Sum(k => this._data[i][k] * matrix._data[k][j]); 138} 139} 140 141return resultMatrix; 142} 143 144public Matrix Inverse() 145{ 146if (_m != _n) 147{ 148throw new InvalidOperationException("只有方阵可以求逆"); 149} 150 151var combinedMatrix = this.Combine(this.E()); 152combinedMatrix = combinedMatrix.Simplify(); 153 154var resultMatrix = new Matrix(_m, _m); 155for (var i = 0; i < resultMatrix._m; i++) 156{ 157Array.Copy(combinedMatrix._data[i], resultMatrix._m, resultMatrix._data[i], 0, resultMatrix._m); 158} 159 160return resultMatrix; 161} 162 163public Matrix Combine(Matrix matrix) 164{ 165if (this._m != matrix._m) 166{ 167throw new InvalidOperationException("左侧矩阵的行不等于右侧矩阵的行"); 168} 169 170var resultMatrix = new Matrix(this._m, this._n + matrix._n); 171for (var i = 0; i < resultMatrix._m; i++) 172{ 173Array.Copy(this._data[i], 0, resultMatrix._data[i], 0, this._data[i].Length); 174Array.Copy(matrix._data[i], 0, resultMatrix._data[i], this._data[i].Length, matrix._data[i].Length); 175} 176 177return resultMatrix; 178} 179 180public Matrix E() 181{ 182return E(_m); 183} 184 185public static Matrix E(int m) 186{ 187var matrix = new Matrix(m, m); 188for (var i = 0; i < m; i++) 189{ 190matrix._data[i][i] = 1; 191} 192 193return matrix; 194} 195 196public Matrix ConeSelf() 197{ 198var resultMatrix = new Matrix(this._m, this._n); 199for (var i = 0; i < this._m; i++) 200{ 201Array.Copy(this._data[i], resultMatrix._data[i], this._n); 202} 203 204return resultMatrix; 205} 206 207public void Dispaly() 208{ 209Console.WriteLine(); 210foreach (var row in _data) 211{ 212Console.WriteLine("[ " + String.Join(" , ", row) + " ]"); 213} 214Console.WriteLine(); 215} 216 217private int FindNonZeroRowIndex(int col, int startRow) 218{ 219if (startRow >= _m) 220{ 221return -1; 222} 223 224for (var i = startRow; i < _m; i++) 225{ 226if (_data[i][col] != 0) 227{ 228return i; 229} 230} 231 232return -1; 233} 234} 235} 236 }

备注 【数学(《线性代数》矩阵乘积|数学:《线性代数》矩阵乘积 之 代码实现)】上例中的几个变换方法都实现为了无副作用的,面向数学概念的结构最好实现为这样的,因为数学中的方法就是无副作用的。

    推荐阅读