计算方法(三)C#矩阵类库
测量平差以及工科中常常用到矩阵的相关运算,因此自己写了一个,同时考虑到了类库的可用性,这次又重载了比较匀运算符,修正了一些问题
using System;
using System.Collections.Generic; namespace CMath
{
[Serializable]
public class Matrix
{
public double[] element;
private int rows = ;
private int cols = ;
/// <summary>
/// 获取矩阵行数
/// </summary>
public int Rows
{
get
{
return rows;
}
}
/// <summary>
/// 获取矩阵列数
/// </summary>
public int Cols
{
get
{
return cols;
}
}
/// <summary>
/// 获取或设置第i行第j列的元素值
/// </summary>
/// <param name="i">第i行</param>
/// <param name="j">第j列</param>
/// <returns>返回第i行第j列的元素值</returns>
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;
}
}
/// <summary>
/// 用二维数组初始化Matrix
/// </summary>
/// <param name="m">二维数组</param>
public Matrix(double[][] m)
{
this.rows = m.GetLength();
this.cols = m.GetLength();
int count = ;
this.element=new double[Rows*Cols];
for (int i = ; i < rows; i++)
{
for (int j = ; j < cols; j++)
{
element[count++] = m[i][j];
}
}
}
public Matrix(double[,] m)
{
this.rows = m.GetLength();
this.cols = m.GetLength();
this.element = new double[this.rows * this.cols];
int count = ;
for (int i = ; i < rows; i++)
{
for (int j = ; j < cols; j++)
{
element[count++] = m[i, j];
}
}
}
public Matrix(List<List<double>> m)
{
this.rows = m.Count;
this.cols = m[].Count;
this.element = new double[Rows * Cols];
for (int i = ; i < rows; i++)
{
for (int j = ; j < cols; j++)
{
this[i, j] = m[i][j];
}
}
}
#region 矩阵数学运算
public static Matrix MAbs(Matrix a)
{
Matrix _thisCopy = a.DeepCopy();
for (int i = ; i < a.Rows; i++)
{
for (int j = ; j < a.Cols; j++)
{
_thisCopy[i, j] = Math.Abs(a[i, j]);
}
}
return _thisCopy;
}
/// <summary>
/// 矩阵相加
/// </summary>
/// <param name="a">第一个矩阵,和b矩阵必须同等大小</param>
/// <param name="b">第二个矩阵</param>
/// <returns>返回矩阵相加后的结果</returns>
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 = ; i < a.Rows; i++)
{
for (int j = ; j < a.Cols; j++)
{
res[i, j] = a[i, j] + b[i, j];
}
}
return new Matrix(res);
}
else
{
throw new Exception("两个矩阵行列不相等");
}
}
/// <summary>
/// 矩阵相减
/// </summary>
/// <param name="a">第一个矩阵,和b矩阵必须同等大小</param>
/// <param name="b">第二个矩阵</param>
/// <returns>返回矩阵相减后的结果</returns>
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 = ; i < a.Rows; i++)
{
for (int j = ; j < a.Cols; j++)
{
res[i, j] = a[i, j] - b[i, j];
}
}
return new Matrix(res);
}
else
{
throw new Exception("两个矩阵行列不相等");
}
}
/// <summary>
/// 对矩阵每个元素取相反数
/// </summary>
/// <param name="a">二维矩阵</param>
/// <returns>得到矩阵的相反数</returns>
public static Matrix operator -(Matrix a)
{
Matrix res = a;
for (int i = ; i < a.rows; i++)
{
for (int j = ; j < a.cols; j++)
{
res.element[i * a.cols + j] = -res.element[i * a.cols + j];
}
}
return res;
}
/// <summary>
/// 矩阵相乘
/// </summary>
/// <param name="a">第一个矩阵</param>
/// <param name="b">第二个矩阵,这个矩阵的行要与第一个矩阵的列相等</param>
/// <returns>返回相乘后的一个新的矩阵</returns>
public static Matrix operator *(Matrix a, Matrix b)
{
if (a.cols == b.rows)
{
double[,] res = new double[a.rows, b.cols];
for (int i = ; i < a.rows; i++)
{
for (int j = ; j < b.cols; j++)
{
for (int k = ; k < a.cols; k++)
{
res[i, j] += a[i, k] * b[k, j];
}
}
}
return new Matrix(res);
}
else
{
throw new Exception("两个矩阵行和列不等");
}
}
/// <summary>
/// 矩阵与数相乘
/// </summary>
/// <param name="a">第一个矩阵</param>
/// <param name="num">一个实数</param>
/// <returns>返回相乘后的新的矩阵</returns>
public static Matrix operator *(Matrix a, double num)
{
Matrix res = a;
for (int i = ; i < a.rows; i++)
{
for (int j = ; j < a.cols; j++)
{
res.element[i * a.cols + j] *= num;
}
}
return res;
}
/// <summary>
/// 矩阵转置
/// </summary>
/// <returns>返回当前矩阵转置后的新矩阵</returns>
public Matrix Transpose()
{
double[,] res = new double[cols, rows];
{
for (int i = ; i < cols; i++)
{
for (int j = ; j < rows; j++)
{
res[i, j] = this[j, i];
}
}
}
return new Matrix(res);
}
/// <summary>
/// 矩阵求逆
/// </summary>
/// <returns>返回求逆后的新的矩阵</returns>
public Matrix Inverse()
{
//最后原始矩阵并不变,所以需要深拷贝一份
Matrix _thisCopy = this.DeepCopy();
if (cols == rows && this.Determinant() != )
{
//初始化一个同等大小的单位阵
Matrix res = _thisCopy.EMatrix();
for (int i = ; 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, -, r);
res.Exchange(i, -, r);
//消元
for (int j = ; 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 = ; i < a.Rows; i++)
{
for (int j = ; 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 = ; i < a.Rows; i++)
{
for (int j = ; 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 = ; i < a.Rows; i++)
{
for (int j = ; 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 = ; i < a.Rows; i++)
{
for (int j = ; 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 = ; i < a.Rows; i++)
{
for (int j = ; 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 = ; i < a.Rows; i++)
{
for (int j = ; 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 = ;
for (int i = ; 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 *= -;
}
//消元
for (int j = i + ; j < rows; j++)
{
double r = -_thisCopy[j, i] / _thisCopy[i, i];
_thisCopy.Exchange(i, j, r);
}
}
//计算对角线乘积
for (int i = ; i < rows; i++)
{
res *= _thisCopy[i, i];
}
return res;
}
else
{
throw new Exception("不是行列式");
}
}
#endregion
#region 初等变换
/// <summary>
/// 初等变换:交换第r1和第r2行
/// </summary>
/// <param name="r1">第r1行</param>
/// <param name="r2">第r2行</param>
/// <returns>返回交换两行后的新的矩阵</returns>
public Matrix Exchange(int r1, int r2)
{
if (Math.Min(r2, r1) >= && Math.Max(r1, r2) < rows)
{
for (int j = ; j < cols; j++)
{
double temp = this[r1, j];
this[r1, j] = this[r2, j];
this[r2, j] = temp;
}
return this;
}
else
{
throw new Exception("超出索引");
}
}
/// <summary>
/// 初等变换:将r1行乘以某个数加到r2行
/// </summary>
/// <param name="r1">第r1行乘以num</param>
/// <param name="r2">加到第r2行,若第r2行为负,则直接将r1乘以num并返回</param>
/// <param name="num">某行放大的倍数</param>
/// <returns></returns>
public Matrix Exchange(int r1, int r2, double num)
{
if (Math.Min(r2, r1) >= && Math.Max(r1, r2) < rows)
{
for (int j = ; j < cols; j++)
{
this[r2, j] += this[r1, j] * num;
}
return this;
}
else if (r2 < )
{
for (int j = ; j < cols; j++)
{
this[r1, j] *= num;
}
return this;
}
else
{
throw new Exception("超出索引");
}
}
/// <summary>
/// 得到一个同等大小的单位矩阵
/// </summary>
/// <returns>返回一个同等大小的单位矩阵</returns>
public Matrix EMatrix()
{
if (rows == cols)
{
double[,] res = new double[rows, cols];
for (int i = ; i < rows; i++)
{
for (int j = ; j < cols; j++)
{
if (i == j)
res[i, j] = ;
else
res[i, j] = ;
}
}
return new Matrix(res);
}
else
throw new Exception("不是方阵,无法得到单位矩阵");
}
#endregion
/// <summary>
/// 深拷贝,仅仅将值拷贝给一个新的对象
/// </summary>
/// <returns>返回深拷贝后的新对象</returns>
public Matrix DeepCopy()
{
double[,] ele = new double[rows, cols];
for (int i = ; i < rows; i++)
{
for (int j = ; j < cols; j++)
{
ele[i, j] = this[i, j];
}
}
return new Matrix(ele);
} public override string ToString()
{
string str = "";
for (int i = ; i < Rows; i++)
{
for (int j = ; j < Cols; j++)
{
str += this[i, j].ToString();
if (j != Cols - )
str += " ";
else if (i != Rows - )
str += Environment.NewLine;
}
}
return str;
}
}
}
矩阵的求秩过几天补上。
计算方法(三)C#矩阵类库的更多相关文章
- P4888 三去矩阵
P4888 三去矩阵 给出一个字符矩阵, 多次询问求以 \((x, y)\) 为中心的最长回文串长度(即横竖两种) \(l, q <= 2000\) Solution 数据范围小直接模拟即可 C ...
- 3D数学基础(三)矩阵
3D引擎中对于矩阵的使用非常多,介绍这些知识也是为了告诉开发者原理,更有助于开发者编写逻辑. (1)固定流水线 各种坐标系之间的转化是通过矩阵相乘得到的,这里面就涉及到了3D固定流水线.作为3D游戏开 ...
- python 矩阵分成上三角下三角和对角三个矩阵
diagonal Return specified diagonals. diagflat Create a 2-D array with the flattened input as a diago ...
- hihoCoder #1162 : 骨牌覆盖问题·三 (矩阵快速幂,DP)
题意:有一个k*n的棋盘,要求用1*2的骨牌来铺满,有多少种方案?(k<8,n<100000001) 思路: 由于k是比较小,但是又不那么小,可以专门构造这样的一个矩阵M,使得只要我们有一 ...
- Azure KeyVault(三)通过 Microsoft.Azure.KeyVault 类库在 .NET Core 上获取 Secrets
一,引言 上一篇文章,我们介绍了 Azure Key Vault 在实际项目中的用途,Azure Key Vault 作为密钥管理的服务,我们可以很轻松的利用它创建和控制用于加密的密钥,和管理证书和机 ...
- 机器学习中的矩阵方法04:SVD 分解
前面我们讲了 QR 分解有一些优良的特性,但是 QR 分解仅仅是对矩阵的行进行操作(左乘一个酉矩阵),可以得到列空间.这一小节的 SVD 分解则是将行与列同等看待,既左乘酉矩阵,又右乘酉矩阵,可以得出 ...
- [WebGL入门]五,矩阵的基础知识
注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中假设有我的额外说明.我会加上[lufy:],另外.鄙人webgl研究还不够深入,一些专业词语,假设翻译有误,欢迎大家指 ...
- 从矩阵(matrix)角度讨论PCA(Principal Component Analysis 主成分分析)、SVD(Singular Value Decomposition 奇异值分解)相关原理
0. 引言 本文主要的目的在于讨论PAC降维和SVD特征提取原理,围绕这一主题,在文章的开头从涉及的相关矩阵原理切入,逐步深入讨论,希望能够学习这一领域问题的读者朋友有帮助. 这里推荐Mit的Gilb ...
- 机器学习 | SVD矩阵分解算法,对矩阵做拆分,然后呢?
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是机器学习专题第28篇文章,我们来聊聊SVD算法. SVD的英文全称是Singular Value Decomposition,翻译过来 ...
随机推荐
- Razor引擎的转换数据类型
AsInt() 把字符串转换为整数. if (myString.IsInt()) IsInt() {myInt=myString.AsInt();} AsFloat() 把字符串转换为浮点数. if ...
- 使用django-mssql时候报pythoncom模块不存在
pip install django-mssql是链接sqlserver的数据库db引擎,这里用到了pythoncom模块,所以还需要安装 pip install pypiwin32 settings ...
- 使用cglib动态创建java类
转至:http://ckwang17.iteye.com/blog/963881 cglib 是一个开源项目! 是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Jav ...
- 调试器带参数调试(OD,EDB)
小东西,不要在意这些细节-- OD带参数比较简单: 文件-- 打开 -- 在最下面有一个参数 KALI LINUX下的EDB 命令格式为 edb –run "对应程序路径" ...
- About Technology Research
做了大量的了解(research).尝试(experimental).探索(exploration).摸索(groping); 解决方案的选择时,要做前期的调研和Demo尝试. 对各方面的技术都做了一 ...
- Remember the Word
uvalive3942:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&pag ...
- Web分析日志
http://www.docin.com/p-649515490.html http://wenku.baidu.com/link?url=kB-83fbl1Zc3Y6U2BYLj-lKMWShe8Z ...
- 【HDOJ】2150 Pipe
计算几何的基础题目.是时候刷刷计算几何了. /* 2150 */ #include <cstdio> #include <cstring> #include <cstdl ...
- Linux下查看进程(程序)启动时的环境变量
背景: 因最近试安装Linux下的jira,有一个中文插件安装后,一旦设置开机启动后,它是英文,而在终端再重新启动一次后呢,似乎插件生效,它又恢复为正常中文界面,我首先想这这涉及到一个环境变量的问题, ...
- cryptopp开源库的使用(一):md5加密
项目总是各种新需求,最近遇到需要对字符串进行md5加密,确保传输字符串的有效性. 考虑到跨平台性和通用性,选择了cryptopp开源库,这里主要是用静态库调用. 1.引入头文件和lib库 #inclu ...