测量平差以及工科中常常用到矩阵的相关运算,因此自己写了一个,同时考虑到了类库的可用性,这次又重载了比较匀运算符,修正了一些问题

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#矩阵类库的更多相关文章

  1. P4888 三去矩阵

    P4888 三去矩阵 给出一个字符矩阵, 多次询问求以 \((x, y)\) 为中心的最长回文串长度(即横竖两种) \(l, q <= 2000\) Solution 数据范围小直接模拟即可 C ...

  2. 3D数学基础(三)矩阵

    3D引擎中对于矩阵的使用非常多,介绍这些知识也是为了告诉开发者原理,更有助于开发者编写逻辑. (1)固定流水线 各种坐标系之间的转化是通过矩阵相乘得到的,这里面就涉及到了3D固定流水线.作为3D游戏开 ...

  3. python 矩阵分成上三角下三角和对角三个矩阵

    diagonal Return specified diagonals. diagflat Create a 2-D array with the flattened input as a diago ...

  4. hihoCoder #1162 : 骨牌覆盖问题·三 (矩阵快速幂,DP)

    题意:有一个k*n的棋盘,要求用1*2的骨牌来铺满,有多少种方案?(k<8,n<100000001) 思路: 由于k是比较小,但是又不那么小,可以专门构造这样的一个矩阵M,使得只要我们有一 ...

  5. Azure KeyVault(三)通过 Microsoft.Azure.KeyVault 类库在 .NET Core 上获取 Secrets

    一,引言 上一篇文章,我们介绍了 Azure Key Vault 在实际项目中的用途,Azure Key Vault 作为密钥管理的服务,我们可以很轻松的利用它创建和控制用于加密的密钥,和管理证书和机 ...

  6. 机器学习中的矩阵方法04:SVD 分解

    前面我们讲了 QR 分解有一些优良的特性,但是 QR 分解仅仅是对矩阵的行进行操作(左乘一个酉矩阵),可以得到列空间.这一小节的 SVD 分解则是将行与列同等看待,既左乘酉矩阵,又右乘酉矩阵,可以得出 ...

  7. [WebGL入门]五,矩阵的基础知识

    注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中假设有我的额外说明.我会加上[lufy:],另外.鄙人webgl研究还不够深入,一些专业词语,假设翻译有误,欢迎大家指 ...

  8. 从矩阵(matrix)角度讨论PCA(Principal Component Analysis 主成分分析)、SVD(Singular Value Decomposition 奇异值分解)相关原理

    0. 引言 本文主要的目的在于讨论PAC降维和SVD特征提取原理,围绕这一主题,在文章的开头从涉及的相关矩阵原理切入,逐步深入讨论,希望能够学习这一领域问题的读者朋友有帮助. 这里推荐Mit的Gilb ...

  9. 机器学习 | SVD矩阵分解算法,对矩阵做拆分,然后呢?

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是机器学习专题第28篇文章,我们来聊聊SVD算法. SVD的英文全称是Singular Value Decomposition,翻译过来 ...

随机推荐

  1. linux的du和df命令

    今天也有同学问我Linux下查看目录大小的命令,现在也将前阵子学习到du/df两个命令总结一下吧.前阵子测试工作中有遇到过由于磁盘空间满导致程序无法执行到情况,所以使用了df和du两个命令. du查看 ...

  2. javascript关于原型的深刻理解

    Javascript继承机制的设计思想   作者: 阮一峰 日期: 2011年6月 5日 我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类&qu ...

  3. bootstrap首页制作

    <!DOCTYPE html><html><head> <meta charset="utf-8"> <title>我的 ...

  4. js删除选中的复选框中的父辈。

    function scsx(){ var cb=document.getElementsByName('checkbox') if(confirm('删除?')){ for (var i=0;i< ...

  5. CSS 去除浏览器默认 轮廓外框

    在默认情况下,点击 a 标签,input,或者添加click事件的时候,浏览器留下一个轮廓外框(chrome之下为蓝色)~ 然而这些默认的轮廓外框,有时候很影响美观,并不是我们想保留的. 我们应如何消 ...

  6. 纯js实现分页

    原理:所有数据已加载好,js通过遍历部分显示,实现分页效果 html代码 <html> <head> <meta charset='utf-8'> <scri ...

  7. 【手机安全卫士01】项目Splash页面的开发与设计

    首先建立一个安卓的项目,然后修改manifest.xml文件,修改应用程序的logo和显示名称,效果图如下: 对应的代码如下: <?xml version="1.0" enc ...

  8. Ubuntu 启用root账户

    设置分配很简单,只要为root设置一个root密码就行了: $ sudo passwd root 之后会提示要输入root用户的密码,连续输入root密码,再使用:$ su 就可以切换成超级管理员用户 ...

  9. Web日志分析

    http://www.rising.com.cn/newsletter/news/2013-03-20/13380.html https://www.trustwave.com/Resources/S ...

  10. kibaba 选择字段