线性代数之行列式的C#研究实现
最近学习机器学习 才发现以前数学没有学好 开始从线性代数开始学起 读完行列式一章写了些C#的代码学习一下。
直接上C#代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO; namespace LYF.Math
{
/// <summary>
/// 行列式 Determinant
/// </summary>
[SerializableAttribute]
[ComVisibleAttribute(true)]
public class Determinant<T> where T : IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T>
{
T[,] tarr = null;
public Determinant(int n)
{
tarr = new T[n, n];
} public Determinant(T[,] arrT)
{
if (arrT == null || arrT.GetLength(0) != arrT.GetLength(1) || arrT.GetLength(0) < 1)
{
throw new MathException("不正确的数组(数组必须行列数相同且大于1)");
}
else
{
tarr=new T[arrT.GetLength(0),arrT.GetLength(0)];
SetItem(arrT);
}
} /// <summary>
/// 获取元素值
/// </summary>
/// <param name="i"></param>
/// <param name="j"></param>
/// <returns></returns>
public T this[int i, int j]
{
//实现索引器的get方法
get
{
return GetItem(i, j);
} //实现索引器的set方法
set
{
SetItem(i, j, value);
}
} /// <summary>
/// 获取元素的余子式
/// </summary>
/// <param name="i"></param>
/// <param name="j"></param>
/// <returns></returns>
public Determinant<T> A(int i, int j)
{
if (N == 1)
{
return null;
}
else if (i>N||j>N)
{
return null;
}
else
{
Determinant<T> a = new Determinant<T>(N - 1);
for (int m = 1; m <= N - 1; m++)
{
for (int n = 1; n <= N - 1; n++)
{
int p = m, q = n;
if (p >= i)
{
p = m + 1;
}
if (q >= j)
{
q = n + 1;
}
a[m, n] = this[p,q];
}
}
return a;
}
} /// <summary>
/// 设置行列式的值
/// </summary>
/// <param name="i">行数(从1开始)</param>
/// <param name="j">列数(从1开始)</param>
/// <param name="value">值</param>
public void SetItem(int i, int j, T value)
{
if (tarr == null)
{
throw new MathException("行列式未正确初始化");
}
else if (i > N || j > N)
{
throw new MathException("超出行列式索引范围");
}
else
{
tarr[i - 1, j - 1] = value;
}
} public void SetItem(T[,] arrT)
{
if (arrT == null || tarr == null)
{
throw new MathException("不能为空");
}
else if (arrT.GetLength(0) != N || arrT.GetLength(1) != N)
{
throw new MathException("传入阶数不同");
}
else
{
for (int m = 0; m <=N-1; m++)
{
for (int n = 0; n <= N- 1; n++)
{
this[m + 1, n + 1] = arrT[m, n];
}
}
}
} /// <summary>
/// 设置行列式的值
/// </summary>
/// <param name="i">行数(从1开始)</param>
/// <param name="j">列数(从1开始)</param>
/// <param name="value">值</param>
public T GetItem(int i, int j)
{
if (tarr == null)
{
throw new MathException("行列式未正确初始化");
}
else if (i > N || j > N)
{
throw new MathException("超出行列式索引范围");
}
else
{
return tarr[i-1, j-1];
}
} /// <summary>
/// 输出行列式信息
/// </summary>
/// <returns></returns>
public override string ToString()
{
StringBuilder sbRs = new StringBuilder();
if(tarr!=null)
{
for (int m = 0; m <= N - 1; m++)
{
for (int n = 0; n <= N - 1; n++)
{
sbRs.Append(string.Format("{0}\t", tarr[m, n]));
}
sbRs.Append("\n");
} }
return sbRs.ToString();
} /// <summary>
/// 获取行列式的阶数
/// </summary>
public int N
{
get{
if (tarr != null)
{
return tarr.GetLength(0);
}
else
{
return 0;
}
} } private string typeName = string.Empty;
private string GetType()
{
if (string.IsNullOrEmpty(typeName))
{
typeName=typeof(T).Name;
File.AppendAllText("E:\\op.txt", typeName);
}
return typeName; } /// <summary>
/// 获取行列式的值
/// </summary>
public T Value
{
get
{
if (N == 1)
{
return tarr[0, 0];
}
else if (N == 2)
{
return Minus(MUL(tarr[0, 0], tarr[1, 1]), MUL(tarr[0, 1], tarr[1, 0]));
}
else
{
T sum = default(T);
for (int i = 1; i <= N; i++)
{
if ((1+i) % 2 == 0)
{
//余子式正值
sum = Add(sum, MUL(this[1, i], this.A(1, i).Value));
}
else
{
//余子式负值
sum = Minus(sum, MUL(this[1, i], this.A(1, i).Value));
}
}
return sum;
} }
} /// <summary>
/// 加法
/// </summary>
/// <param name="left"></param>
/// <param name="right"></param>
/// <returns></returns>
private T Add(T left, T right)
{
switch (GetType())
{
case "Int16":
return ((T)(object)((short)(object)left + (short)(object)right));
case "Int32":
return ((T)(object)((int)(object)left + (int)(object)right));
case "Int64":
return ((T)(object)((long)(object)left + (long)(object)right));
case "Single":
return ((T)(object)((float)(object)left + (float)(object)right));
case "Double":
return ((T)(object)((double)(object)left + (double)(object)right));
case "Decimal":
return ((T)(object)((decimal)(object)left + (decimal)(object)right));
}
throw new MathException("不支持的操作类型");
} /// <summary>
/// 减法
/// </summary>
/// <param name="left"></param>
/// <param name="right"></param>
/// <returns></returns>
private T Minus(T left, T right)
{
switch (GetType())
{
case "Int16":
return ((T)(object)((short)(object)left - (short)(object)right));
case "Int32":
return ((T)(object)((int)(object)left - (int)(object)right));
case "Int64":
return ((T)(object)((long)(object)left - (long)(object)right));
case "Single":
return ((T)(object)((float)(object)left - (float)(object)right));
case "Double":
return ((T)(object)((double)(object)left - (double)(object)right));
case "Decimal":
return ((T)(object)((decimal)(object)left - (decimal)(object)right));
}
throw new MathException("不支持的操作类型");
} /// <summary>
/// 乘法
/// </summary>
/// <param name="left"></param>
/// <param name="right"></param>
/// <returns></returns>
private T MUL(T left, T right)
{
switch (GetType())
{
case "Int16":
return ((T)(object)((short)(object)left * (short)(object)right));
case "Int32":
return ((T)(object)((int)(object)left * (int)(object)right));
case "Int64":
return ((T)(object)((long)(object)left * (long)(object)right));
case "Single":
return ((T)(object)((float)(object)left * (float)(object)right));
case "Double":
return ((T)(object)((double)(object)left * (double)(object)right));
case "Decimal":
return ((T)(object)((decimal)(object)left * (decimal)(object)right));
}
throw new MathException("不支持的操作类型");
} }
}
以上代码就是对行列式的封装 可以求值获得余子式 很基本的东西 求值的话主要用了递归的方式 因为泛型的原因导致计算过程重复拆箱装箱 不过目前好像也没有什么太好的方法了。反正就是学习 所以性能无所谓了。
然后就是调用了直接上调用代码:
int[,] aaa = new int[4, 4]{{1,2,3,6},
{4,5,7,8},
{7,8,9,10},
{3,8,4,3}}; //LYF.Math.Determinant<int> d = new Determinant<int>(4);
LYF.Math.Determinant<int> d = new Determinant<int>(aaa);
d.SetItem(aaa);
Console.WriteLine("当前行列式:");
Console.WriteLine(d.ToString());
Console.WriteLine("余子式M11:");
Console.WriteLine(d.A(1, 1).ToString());
Console.WriteLine("余子式M12:");
Console.WriteLine(d.A(1, 2).ToString());
Console.WriteLine("余子式M22:");
Console.WriteLine(d.A(2, 2).ToString());
Console.WriteLine("N="+d.N);
Console.WriteLine("行列式的值为:"+d.Value.ToString());
Console.Read();
执行结果如下:
线性代数之行列式的C#研究实现的更多相关文章
- CSUOJ 1979 古怪的行列式
Description 这几天,子浩君潜心研究线性代数. 行列式的值定义如下: 其中,τ(j1j2...jn)为排列j1j2...jn的逆序数. 子浩君很厉害的,但是头脑经常短路,所以他会按照行列式值 ...
- 线性代数笔记24——微分方程和exp(At)
原文:https://mp.weixin.qq.com/s/COpYKxQDMhqJRuMK2raMKQ 微分方程指含有未知函数及其导数的关系式,解微分方程就是找出未知函数.未知函数是一元函数的,叫常 ...
- 【线性代数】5-3:克莱姆法则,逆和体积(Cramer's Rule,Inverses,and Volumes)
title: [线性代数]5-3:克莱姆法则,逆和体积(Cramer's Rule,Inverses,and Volumes) categories: Mathematic Linear Algebr ...
- [Swust OJ 643]--行列式的计算(上三角行列式变换)
题目链接:http://acm.swust.edu.cn/problem/643/ Time limit(ms): 1000 Memory limit(kb): 65535 Description ...
- TOJ4537: n阶行列式
4537: n阶行列式 Time Limit(Common/Java):1000MS/3000MS Memory Limit:65536KByteTotal Submit: 28 ...
- Python人工智能之-三大数学难点 !
1. 微积分: 定积分与不定积分.全微分.最小二乘法.二重积分.微分方程与差分方程等... 2. 线性代数: 行列式.矩阵.向量.线性方程组.矩阵的特性和特性向量.二次型等... 3. 概率论和统计学 ...
- NOIP考点
NOIP考点 基础算法 图 树 数论 数据结构 动态规划 搜索 其他算法 省选知识点汇总 图论 数据结构 字符串相关算法及数据结构 数学 计算几何 搜索 动态规划 其他算法 转自:巨佬的博客 加*号是 ...
- [省选]板块(shenben已经AFO!!!)
shenben已经AFO!!! 部分摘抄自网络 同样的,加粗是重点,星号是选学 图论 网络流(dinic,ISAP选一个,费用流写EK就行.*zkw费用流),二分图 点分治,边分治,*动态点分治 树链 ...
- woj1013 Barcelet 字符串 woj1014 Doraemon's Flashlight 几何
title: woj1013 Barcelet 字符串 date: 2020-03-18 18:00:00 categories: acm tags: [acm,字符串,woj] 字符串,字典序. 1 ...
随机推荐
- DevOps之内容分发网络CDN
唠叨话 关于德语噢屁事的知识点,仅提供专业性的精华汇总,具体知识点细节,参考教程网址,如需帮助,请留言. <内容分发网络CDN(Content Delivery Network)> 关于虚 ...
- 页面固定DIV层CSS代码
有时候为了用户体验更好些,网页设计师会把网站导航放在一个固定的DIV层里面,不随滚动条滚动.本方法是利用CSS,position:fixed属性来固定层,fixed是特殊的absolute,即fixe ...
- win10 uwp 无法附加到CoreCLR
本文说的是在vs调试无法附加到CoreCLR.拒绝访问.已经如何去解决,可能带有一定的主观性和局限性,说的东西可能不对或者不符合每个人的预期.如果觉得我有讲的不对的,就多多包含,或者直接关掉这篇文章, ...
- 在centos6编译配置httpd2.4的N种方法
前言 我们使用linux的过程中,一定会用到httpd这个服务,在centos7上,默认安装的httpd就是2.4版本,大家都知道,2.4版本相对之前的版本已经做了改进,用起来更加方便,但是我们的ce ...
- Java中数组的遍历
(I)标准for循环遍历数组 例如代码片段: int [] nums = new int [] {0,1,2,3,4,5,6,7,8,9}; for(int i=0;i<11;i++){ Sys ...
- 【转】C语言产生随机数
原文地址:http://www.cnblogs.com/xianghang123/archive/2011/08/24/2152404.html 在C语言中,rand()函数可以用来产生随机数,但是这 ...
- 使用脚本监控windows服务的方法
以下脚本可监控某一个windows服务,发现其停止就立即重启之. @echo off rem 定义循环间隔时间和监测的服务: set secs=60 set srvname="NetWin ...
- springCloud四:熔断器ribbon--Hystrix
注:前文概念部分摘抄自博客园 纯洁的微笑 熔断器 雪崩效应 在微服务架构中通常会有多个服务层调用,基础服务的故障可能会导致级联故障,进而造成整个系统不可用的情况,这种现象被称为服务雪崩效应.服务雪崩 ...
- 正则和grep——再做正则就去死
grep 文本过滤工具 基本正则表达式 grep 语法 基本正则表达式的元字符 次数匹配 位置锚定 分组 扩展正则表达式 基本正则表达式的元字符 次数匹配 位置锚定 分组 或者 grep的介绍 lin ...
- 聊聊Java的字节码
本文为作者原创,转载请注明出处(http://www.cnblogs.com/mar-q/)by 负赑屃 巴山楚水凄凉地,二十三年弃置身.怀旧空吟闻笛赋,到乡翻似烂柯人.沉舟侧畔千帆过,病树前头万木春 ...