Работа с матрицами в C#
Матрица представляет из себя двумерный массив. Для начала создадим класс матрицы
public class Matrix { private double[,] data; private int m; public int M {get => this.m;} private int n; public int N {get => this.n;} public Matrix(int m, int n) { this.m = m; this.n = n; this.data = new double[m, n]; } }
Пока этот класс явлеятся просто оберткой для двумерного массива.
Начинаем добавлять вспомогательные методы. Сначала добавим метод, позволяющий выполнить какое-либо действие над всеми элементами матрицы.
public void ProcessFunctionOverData(Action<int, int> func) { for(var i = 0; i < this.M; i++) { for(var j = 0; j < this.N; j++) { func(i, j); } } }
Функции высших порядков в C#
Функции высших порядков — это функции, которые как переменные передаются в аргументы других функций. В методе выше аргумент func имеет тип Action
this.ProcessFunctionOverData((i, j) => this.data[i, j] = 0);
Этот вызов присвоит 0 во все элементы матрицы. Стрелочная функция (i, j) => this.data[i, j] = 0 — это и есть наша функция высшего порядка.
Использовать стрелочные функции не обязательно, можно было передавать и метод:
private void SetToZero(int i, int j) { this.data[i, j] = 0; } ... this.ProcessFunctionOverData(this.SetToZero);
Индексаторы в C#
Индексаторы — это свойства, позволяющие обращаться к объекту как к массиву. Добавим такое свойство, позволяющее обращаться к элементам матрицы по индексу
public double this[int x, int y] { get { return this.data[x, y]; } set { this.data[x, y] = value; } }
Теперь к экземпляру класса Matrix можно обращаться как к двумерному массиву.
Умножение матриц на C#
Сначала реализуем умножение матрицы на число. В результате должна получиться матрица того же размера, элементами будут элементы исходной матрицы умноженные на это число.
Перегрузка операторов в C#
Для классов в C# можно определить операторы. Определим оператор умножения, позволяющиу умножить на число.
public static Matrix operator* (Matrix matrix, double value) { var result = new Matrix(matrix.M, matrix.N); result.ProcessFunctionOverData((i, j) => result[i,j] = matrix[i,j] * value); return result; }
Теперь умножить матрицу на число можно с помощью оператора умножения
var testMatrix = new Matrix(2, 3); var multipliedMatrix = testMatrix * 2.1;
Матрицу можно так же умножить на другую матрицу. Результатом будет новая матрица, элементами которой будут скалярные произведения столбцов и строк исходных матриц. Формулу можно посмотреть на википедии
Перегрузка методов в C#
C# позволяет определить несколько методов с одинаковым названием. Воспользуемся этип и сделаем еще одну реализацию оператора умножения, позволяющую умножать матрицу на другую матрицу
public static Matrix operator* (Matrix matrix, Matrix matrix2) { if (matrix.N != matrix2.M) { throw new ArgumentException("matrixes can not be multiplied"); } var result = new Matrix(matrix.M, matrix2.N); result.ProcessFunctionOverData((i, j) => { for(var k = 0; k < matrix.N; k++) { result[i, j] += matrix[i, k] * matrix2[k, j]; } }); return result; }
Весь исходный код можно найти на гитхабе