目录
一.矩阵定义
1.指定简单矩阵的创建
2.特殊矩阵的创建
【Matrix.Ones】
【Matrix.Eye】
【Matrix.Zeros】
【Matrix.Random】
【Matrix.Diag】
二.矩阵的运算
【Matrix.I】
【Matrix.T】
三.矩阵类代码
四.小结
//单行代码创建矩阵(推荐),以2*2的矩阵为例
Matrix a = new Matrix(new double[,] {{2,2},{1,1}});
//多行代码创建矩阵,以2*2的矩阵为例
double[,] a = new double[2,2]{{2,2},{1,1}};
Matrix b = new Matrix(a);
创建元素全为1的矩阵
//生成一个指定阶数的元素全为1的方阵
Matrix a = Matrix.Ones(3);
//输出结果
1 1 1
1 1 1
1 1 1
//生成一个指定行列的矩阵并且其元素全为1
Matrix a = Matrix.Ones(2,3);
//生成结果
1 1 1
1 1 1
创建单位矩阵
//生成一个指定阶数的单位矩阵
Matrix a = Matrix.Eye(3);
//生成结果
1 0 0
0 1 0
0 0 1
创建零矩阵
//生成一个指定阶数的零矩阵
Matrix a = Matrix.Zeros(3);
//输出结果
0 0 0
0 0 0
0 0 0
//生成一个指定行列的零矩阵
Matrix a = Matrix.Zeros(2,3);
//生成结果
0 0 0
0 0 0
生成随机数矩阵
//创建指定维数的伪随机数矩阵(0-1)
Matrix a = Matrix.Random(2);
//输出结果
0.516404123751635 0.983861273147101
0.899167415173337 0.00153744081106849
//创建指定行和列的伪随机数矩阵
Matrix a = Matrix.Random(2,3);
//输出结果
7.96839595212061E-05 0.147591004682514 0.695700505606691
0.0767334909535635 0.380114347850957 0.248828622628389
//创建指定维数,并且指定随机数范围的伪随机数矩阵(min-max)
Matrix a = Matrix.Random(2,10,20)
//输出结果
15.3690170521704 11.5182845441244
13.8757416298034 19.5315619183386
//创建指定行数,列数,并且指定随机数范围的伪随机数矩阵
Matrix a = Matrix.Random(2,3,10,20)
//输出结果
17.6909273945219 12.7356204915492 15.4563716824429
16.8744842786689 15.6722028579899 15.3704242572982
创建对角矩阵
//创建指定数据的对角矩阵(单行)
Matrix a = Matrix.Diag(new double[]{2,1,3})
//输出结果
2 0 0
0 1 0
0 0 3
矩阵相加减,矩阵乘法与基本矩阵运算相同
矩阵求逆
//矩阵求逆
Matrix a = new Matrix ();
Matrix b = a.I;
矩阵求转置
//矩阵求转置
Matrix a = new Matrix ;
Matrix b = a.T;
using System;
using System.Collections.Generic;
namespace Cmath
{
[Serializable] //反射
public class Matrix
{
public double[] element;
private int rows = 0;
private int cols = 0;
private double[,] value;
///
/// 获取矩阵行数
///
public int Rows
{
get
{
return rows;
}
set
{
rows = value;
}
}
///
/// 获取矩阵列数
///
public int Cols
{
get
{
return cols;
}
set
{
cols = value;
}
}
///
/// 获取与设置矩阵元素值的二维数组
///
public double[,] Value
{
get
{
return this.value;
}
set
{
this.value = value;
}
}
///
/// 获取或设置第i行第j列的元素值
///
/// 第i行
/// 第j列
/// 返回第i行第j列的元素值
public double this[int i, int j]
{
get
{
if (i < Rows && j < Cols)
{
return element[i * cols + j];
}
else
{
throw new Exception("索引越界");
}
}
set
{
element[i * cols + j] = value;
}
}
///
/// 用二维数组初始化Matrix
///
/// 二维数组
private Matrix()
{
}
private Matrix(int rows, int cols)
{
this.rows = rows;
this.cols = cols;
this.value = new double[rows, cols];
}
public Matrix(double[][] m) //构造函数
{
this.rows = m.GetLength(0);
this.cols = m.GetLength(1);
int count = 0;
this.element = new double[Rows * Cols];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
element[count++] = m[i][j];
}
}
}
public Matrix(double[,] m)
{
this.rows = m.GetLength(0);
this.cols = m.GetLength(1);
this.element = new double[this.rows * this.cols];
int count = 0;
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
element[count++] = m[i, j];
}
}
}
public Matrix(List> m)
{
this.rows = m.Count;
this.cols = m[0].Count;
this.element = new double[Rows * Cols];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
this[i, j] = m[i][j];
}
}
}
#region 特殊矩阵的生成
///
/// 生成一个指定阶的元素全为1的方阵
///
///
///
public static Matrix Ones(int dimension)
{
Matrix result = new Matrix();
result.rows = dimension;
result.cols = dimension;
result.value = new double[dimension, dimension];
result.element = new double[dimension * dimension];
int count = 0;
for (int i = 0; i < dimension; i++)
for (int j = 0; j < dimension; j++)
{
result.value[i, j] = 1;
result.element[count++] = 1 ;
}
return result;
}
///
/// 生成一个指定行列的元素全为1的矩阵
///
///
///
///
public static Matrix Ones(int row, int column)
{
Matrix result = new Matrix();
result.rows = row;
result.cols = column;
result.value = new double[row, column];
result.element = new double[row * column];
int count = 0;
for (int i = 0; i < row; i++)
for (int j = 0; j < column; j++)
{
result.value[i, j] = 1;
result.element[count++] = 1;
}
return result;
}
///
/// 生成一个指定阶数的单位矩阵
///
///
///
public static Matrix Eye(int dimension)
{
Matrix result = new Matrix();
result.rows = dimension;
result.cols = dimension;
result.value = new double[dimension, dimension];
result.element = new double[dimension * dimension];
int count = 0;
for (int i = 0; i < dimension; i++)
for (int j = 0; j < dimension; j++)
{
if (i == j)
{
result.value[i, j] = 1;
result.element[count] = 1;
}
else
{
result.value[i, j] = 0;
result.element[count] = 0;
}
count++;
}
return result;
}
///
/// 生成一个指定阶数的零矩阵
///
///
///
public static Matrix Zeros(int dimension)
{
Matrix result = new Matrix();
result.rows = dimension;
result.cols = dimension;
result.value = new double[dimension, dimension];
result.element = new double[dimension * dimension];
int count = 0;
for (int i = 0; i < dimension; i++)
for (int j = 0; j < dimension; j++)
{
result.value[i, j] = 0;
result.element[count++] = 0;
}
return result;
}
///
/// 生成一个指定行列数的零矩阵
///
///
///
///
public static Matrix Zeros(int row, int column)
{
Matrix result = new Matrix();
result.rows = row;
result.cols = column;
result.value = new double[row, column];
result.element = new double[row * column];
int count = 0;
for (int i = 0; i < row; i++)
for (int j = 0; j < column; j++)
{
result.value[i, j] = 0;
result.element[count++] = 0;
}
return result;
}
///
/// 生成一个指定阶数的伪随机数矩阵
///
///
///
public static Matrix Random(int dimension)
{
Matrix result = new Matrix();
result.rows = dimension;
result.cols = dimension;
result.value = new double[dimension, dimension];
result.element = new double[dimension * dimension];
int count = 0;
for (int i = 0; i < dimension; i++)
for (int j = 0; j < dimension; j++)
{
result.value[i, j] = Matrix.GetRandomNum();
result.element[count++] = result.value[i, j];
}
return result;
}
///
/// 生成一个指定行列数的伪随机数矩阵
///
///
///
///
public static Matrix Random(int row, int column)
{
Matrix result = new Matrix();
result.rows = row;
result.cols = column;
result.value = new double[row, column];
result.element = new double[row * column];
int count = 0;
for (int i = 0; i < row; i++)
for (int j = 0; j < column; j++)
{
result.value[i, j] = Matrix.GetRandomNum();
result.element[count++] = result.value[i, j];
}
return result;
}
///
/// 生成一个指定阶数和随机范围的伪随机数矩阵
///
///
/// 伪随机数下限
/// 伪随机数上限
///
public static Matrix Random(int dimension, double min, double max)
{
if (min > max)
{
min = max + min;
max = min - max;
min = min - max;
}
Matrix result = new Matrix();
result.rows = dimension;
result.cols = dimension;
result.value = new double[dimension, dimension];
result.element = new double[dimension * dimension];
int count = 0;
for (int i = 0; i < dimension; i++)
for (int j = 0; j < dimension; j++)
{
result.value[i, j] = Matrix.GetRandomNum() * (max - min) + min;
result.element[count++] = result.value[i, j];
}
return result;
}
///
/// 生成一个指定行列数和伪随机数范围的矩阵
///
///
///
/// 伪随机数下限
/// 伪随机数上限
///
public static Matrix Random(int row, int column, double min, double max)
{
if (min > max)
{
min = max + min;
max = min - max;
min = min - max;
}
Matrix result = new Matrix();
result.rows = row;
result.cols = column;
result.value = new double[row, column];
result.element = new double[row * column];
int count = 0;
for (int i = 0; i < row; i++)
for (int j = 0; j < column; j++)
{
result.value[i, j] = Matrix.GetRandomNum() * (max - min) + min;
result.element[count++] = result.value[i, j];
}
return result;
}
///
/// 生成一个由指定数组元素填充对角线的对角矩阵
///
///
///
public static Matrix Diag(double[] diag)
{
Matrix result = Matrix.Zeros(diag.GetLength(0));
for (int i = 0; i < result.rows; i++)
{
result.value[i, i] = diag[i];
result.element[i * result.rows + i] = result.value[i, i];
}
return result;
}
#endregion
#region 矩阵数学运算
public static Matrix MAbs(Matrix a)
{
Matrix _thisCopy = a.DeepCopy();
for (int i = 0; i < a.Rows; i++)
{
for (int j = 0; j < a.Cols; j++)
{
_thisCopy[i, j] = Math.Abs(a[i, j]);
}
}
return _thisCopy;
}
///
/// 矩阵相加
///
/// 第一个矩阵,和b矩阵必须同等大小
/// 第二个矩阵
/// 返回矩阵相加后的结果
public static Matrix operator +(Matrix a, Matrix b)
{
if (a.cols == b.cols && a.rows == b.rows)
{
double[,] res = new double[a.rows, a.cols];
for (int i = 0; i < a.Rows; i++)
{
for (int j = 0; j < a.Cols; j++)
{
res[i, j] = a[i, j] + b[i, j];
}
}
return new Matrix(res);
}
else
{
throw new Exception("两个矩阵行列不相等");
}
}
///
/// 矩阵相减
///
/// 第一个矩阵,和b矩阵必须同等大小
/// 第二个矩阵
/// 返回矩阵相减后的结果
public static Matrix operator -(Matrix a, Matrix b)
{
if (a.cols == b.cols && a.rows == b.rows)
{
double[,] res = new double[a.rows, a.cols];
for (int i = 0; i < a.Rows; i++)
{
for (int j = 0; j < a.Cols; j++)
{
res[i, j] = a[i, j] - b[i, j];
}
}
return new Matrix(res);
}
else
{
throw new Exception("两个矩阵行列不相等");
}
}
///
/// 对矩阵每个元素取相反数
///
/// 二维矩阵
/// 得到矩阵的相反数
public static Matrix operator -(Matrix a)
{
Matrix res = a;
for (int i = 0; i < a.rows; i++)
{
for (int j = 0; j < a.cols; j++)
{
res.element[i * a.cols + j] = -res.element[i * a.cols + j];
}
}
return res;
}
///
/// 矩阵相乘
///
/// 第一个矩阵
/// 第二个矩阵,这个矩阵的行要与第一个矩阵的列相等
/// 返回相乘后的一个新的矩阵
public static Matrix operator *(Matrix a, Matrix b)
{
if (a.cols == b.rows)
{
double[,] res = new double[a.rows, b.cols];
for (int i = 0; i < a.rows; i++)
{
for (int j = 0; j < b.cols; j++)
{
for (int k = 0; k < a.cols; k++)
{
res[i, j] += a[i, k] * b[k, j];
}
}
}
return new Matrix(res);
}
else
{
throw new Exception("两个矩阵行和列不等");
}
}
///
/// 矩阵与数相乘
///
/// 第一个矩阵
/// 一个实数
/// 返回相乘后的新的矩阵
public static Matrix operator *(Matrix a, double num)
{
Matrix res = a;
for (int i = 0; i < a.rows; i++)
{
for (int j = 0; j < a.cols; j++)
{
res.element[i * a.cols + j] *= num;
}
}
return res;
}
///
/// 矩阵转置
///
/// 返回当前矩阵转置后的新矩阵
public Matrix T()
{
double[,] res = new double[cols, rows];
{
for (int i = 0; i < cols; i++)
{
for (int j = 0; j < rows; j++)
{
res[i, j] = this[j, i];
}
}
}
return new Matrix(res);
}
///
/// 矩阵求逆
///
/// 返回求逆后的新的矩阵
public Matrix I()
{
//最后原始矩阵并不变,所以需要深拷贝一份
Matrix _thisCopy = this.DeepCopy();
if (cols == rows && this.Determinant() != 0)
{
//初始化一个同等大小的单位阵
Matrix res = _thisCopy.EMatrix();
for (int i = 0; i < rows; i++)
{
//首先找到第i列的绝对值最大的数,并将该行和第i行互换
int rowMax = i;
double max = Math.Abs(_thisCopy[i, i]);
for (int j = i; j < rows; j++)
{
if (Math.Abs(_thisCopy[j, i]) > max)
{
rowMax = j;
max = Math.Abs(_thisCopy[j, i]);
}
}
//将第i行和找到最大数那一行rowMax交换
if (rowMax != i)
{
_thisCopy.Exchange(i, rowMax);
res.Exchange(i, rowMax);
}
//将第i行做初等行变换,将第一个非0元素化为1
double r = 1.0 / _thisCopy[i, i];
_thisCopy.Exchange(i, -1, r);
res.Exchange(i, -1, r);
//消元
for (int j = 0; j < rows; j++)
{
//到本行后跳过
if (j == i)
continue;
else
{
r = -_thisCopy[j, i];
_thisCopy.Exchange(i, j, r);
res.Exchange(i, j, r);
}
}
}
return res;
}
else
{
throw new Exception("矩阵不是方阵无法求逆");
}
}
#region 重载比较运算符
public static bool operator <(Matrix a, Matrix b)
{
bool issmall = true;
for (int i = 0; i < a.Rows; i++)
{
for (int j = 0; j < a.Cols; j++)
{
if (a[i, j] >= b[i, j]) issmall = false;
}
}
return issmall;
}
public static bool operator >(Matrix a, Matrix b)
{
bool issmall = true;
for (int i = 0; i < a.Rows; i++)
{
for (int j = 0; j < a.Cols; j++)
{
if (a[i, j] <= b[i, j]) issmall = false;
}
}
return issmall;
}
public static bool operator <=(Matrix a, Matrix b)
{
bool issmall = true;
for (int i = 0; i < a.Rows; i++)
{
for (int j = 0; j < a.Cols; j++)
{
if (a[i, j] > b[i, j]) issmall = false;
}
}
return issmall;
}
public static bool operator >=(Matrix a, Matrix b)
{
bool issmall = true;
for (int i = 0; i < a.Rows; i++)
{
for (int j = 0; j < a.Cols; j++)
{
if (a[i, j] < b[i, j]) issmall = false;
}
}
return issmall;
}
public static bool operator !=(Matrix a, Matrix b)
{
bool issmall = true;
issmall = ReferenceEquals(a, b);
if (issmall) return issmall;
for (int i = 0; i < a.Rows; i++)
{
for (int j = 0; j < a.Cols; j++)
{
if (a[i, j] == b[i, j]) issmall = false;
}
}
return issmall;
}
public static bool operator ==(Matrix a, Matrix b)
{
bool issmall = true;
issmall = ReferenceEquals(a, b);
if (issmall) return issmall;
for (int i = 0; i < a.Rows; i++)
{
for (int j = 0; j < a.Cols; j++)
{
if (a[i, j] != b[i, j]) issmall = false;
}
}
return issmall;
}
public override bool Equals(object obj)
{
Matrix b = obj as Matrix;
return this == b;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
#endregion
public double Determinant()
{
if (cols == rows)
{
Matrix _thisCopy = this.DeepCopy();
//行列式每次交换行,都需要乘以-1
double res = 1;
for (int i = 0; i < rows; i++)
{
//首先找到第i列的绝对值最大的数
int rowMax = i;
double max = Math.Abs(_thisCopy[i, i]);
for (int j = i; j < rows; j++)
{
if (Math.Abs(_thisCopy[j, i]) > max)
{
rowMax = j;
max = Math.Abs(_thisCopy[j, i]);
}
}
//将第i行和找到最大数那一行rowMax交换,同时将单位阵做相同初等变换
if (rowMax != i)
{
_thisCopy.Exchange(i, rowMax);
res *= -1;
}
//消元
for (int j = i + 1; j < rows; j++)
{
double r = -_thisCopy[j, i] / _thisCopy[i, i];
_thisCopy.Exchange(i, j, r);
}
}
//计算对角线乘积
for (int i = 0; i < rows; i++)
{
res *= _thisCopy[i, i];
}
return res;
}
else
{
throw new Exception("不是行列式");
}
}
#endregion
#region 初等变换
///
/// 初等变换:交换第r1和第r2行
///
/// 第r1行
/// 第r2行
/// 返回交换两行后的新的矩阵
public Matrix Exchange(int r1, int r2)
{
if (Math.Min(r2, r1) >= 0 && Math.Max(r1, r2) < rows)
{
for (int j = 0; j < cols; j++)
{
double temp = this[r1, j];
this[r1, j] = this[r2, j];
this[r2, j] = temp;
}
return this;
}
else
{
throw new Exception("超出索引");
}
}
///
/// 初等变换:将r1行乘以某个数加到r2行
///
/// 第r1行乘以num
/// 加到第r2行,若第r2行为负,则直接将r1乘以num并返回
/// 某行放大的倍数
///
public Matrix Exchange(int r1, int r2, double num)
{
if (Math.Min(r2, r1) >= 0 && Math.Max(r1, r2) < rows)
{
for (int j = 0; j < cols; j++)
{
this[r2, j] += this[r1, j] * num;
}
return this;
}
else if (r2 < 0)
{
for (int j = 0; j < cols; j++)
{
this[r1, j] *= num;
}
return this;
}
else
{
throw new Exception("超出索引");
}
}
///
/// 得到一个同等大小的单位矩阵
///
/// 返回一个同等大小的单位矩阵
public Matrix EMatrix()
{
if (rows == cols)
{
double[,] res = new double[rows, cols];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
if (i == j)
res[i, j] = 1;
else
res[i, j] = 0;
}
}
return new Matrix(res);
}
else
throw new Exception("不是方阵,无法得到单位矩阵");
}
#endregion
///
/// 深拷贝,仅仅将值拷贝给一个新的对象
///
/// 返回深拷贝后的新对象
public Matrix DeepCopy()
{
double[,] ele = new double[rows, cols];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
ele[i, j] = this[i, j];
}
}
return new Matrix(ele);
}
///
/// 返回一个伪随机数
///
///
public static double GetRandomNum()
{
Random ran = new Random(Guid.NewGuid().GetHashCode());
return ran.NextDouble();
}
public override string ToString()
{
string str = "";
for (int i = 0; i < Rows; i++)
{
for (int j = 0; j < Cols; j++)
{
str += this[i, j].ToString();
if (j != Cols - 1)
str += " ";
else if (i != Rows - 1)
str += Environment.NewLine;
}
}
return str;
}
}
}
这个矩阵类是根据我个人的习惯进行编写的,我平时比较喜欢用Python编写矩阵,所以在一些函数的命名上和Python基本相同,这个矩阵类目前还有许多地方可以进行改进,比如element这个成员变量如何进行优化,还有传数组是以地址形式,相对比较不安全,以及本矩阵类在一些功能上还不完整,比如求行列式还没有写,希望大家可以互相讨论,有需要的可以根据自己的情况在这个基础上进行改进。