MyMathLib系列(行列式计算)

时间:2023-03-09 15:42:20
MyMathLib系列(行列式计算)

靠人不如靠己,准备做自己得MathLib,在学校的时候,就想过把数学数理的东西都计算机化。但一直没有时间去做这件事情,如今认为空余 时间比較闲,就做做这件事情,先从线性代数開始,毕竟这里面的非常多算法。实际共走中都实用到。

在做这些算法的过程中。也体会到了:数学中的东西不是没实用,而是你没用到。以下的算法(除全排列外)都是自己原创想得,做的不够效率的地方,也请大家分享更好的东西。好了。啰嗦这么多,让代码说话吧:

/// <summary>
/// 行列式计算,本程序属于MyMathLib的一部分。欢迎使用,參考。提意见。 /// 有时间用函数语言改写,做自己得MathLib,里面的算法经过验证,但没经过
/// 严格測试,如需參考,请谨慎.
/// </summary>
public static partial class LinearAlgebra
{
/// <summary>
/// 求逆序数
/// </summary>
/// <param name="Numbers">数字序列</param>
/// <returns></returns>
public static int CalcInverseNumber(string Numbers)
{
int theRet = 0;
if (string.IsNullOrWhiteSpace(Numbers))
{
return theRet;
}
else
{
string[] theNumbers = Numbers.Split(new string[] { ",", " " }, StringSplitOptions.RemoveEmptyEntries);
return CalcInverseNumber(theNumbers);
}
}
/// <summary>
/// 求逆序数
/// </summary>
/// <param name="Numbers">数字序列</param>
/// <returns></returns>
public static int CalcInverseNumber(string[] Numbers)
{
var theRet = 0;
if (Numbers.Count() <= 0)
{
return theRet;
}
else
{
string[] theNumbers = Numbers.ToArray(); int[] theNums = new int[theNumbers.Count()];
for (int i = 0; i < theNumbers.Count(); i++)
{
theNums[i] = Convert.ToInt32(theNumbers[i]);
}
for (int theI = 0; theI < theNums.Count() - 1; theI++)
{
for (int theJ = theI + 1; theJ < theNums.Count(); theJ++)
{
if (theNums[theI] > theNums[theJ])
{
theRet++;
}
}
}
}
return theRet;
}
private static string HandlingMultiExp(string Exp, int Sign)
{
decimal theRetNum = Sign;
var theRetLine = "";
var theDigits = Exp.Split('*');
foreach (var theD in theDigits)
{
decimal theDec = 0;
if (decimal.TryParse(theD, out theDec))
{
theRetNum *= theDec;
}
else
{
if (theRetLine == "")
{
theRetLine = theD;
}
else
{
theRetLine += "*" + theD;
}
}
}
if (theRetNum == 0)
{
return "";
}
else
{
if (theRetNum == 1)
{
return theRetLine;
}
if (theRetNum == -1)
{
return "-" + theRetLine;
}
return theRetNum.ToString() + theRetLine;
}
}
/// <summary>
/// 行列式表达式展开
/// </summary>
/// <param name="Determinants">N阶行列式</param>
/// <returns></returns>
public static string DeterminantToExpression(string[,] Determinants)
{
int theR = Determinants.GetLength(0);
int theC = Determinants.GetLength(1);
if (theR != theC)
{
throw new Exception("不是N阶行列式!");
}
var theResults = new List<string>();
List<string> theNs = new List<string>();
for (int i = 1; i <= theC; i++)
{
theNs.Add(i.ToString());
}
FullPermutation(theNs, 0, theC - 1, theResults);
var theNExp = "";
var thePExp = "";
foreach (var theAL in theResults)
{
var theInverseNum = Convert.ToInt32(Math.Pow(-1, CalcInverseNumber(theAL)));
var theLine = "";
string[] theNums = theAL.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 1; i <= theC; i++)
{
var theV = Determinants[i - 1, int.Parse(theNums[i - 1]) - 1];
theLine += "*" + theV;
}
theLine = HandlingMultiExp(theLine.Substring(1), theInverseNum);
if (!string.IsNullOrEmpty(theLine))
{
if (theLine[0] == '-')
{
theNExp += "" + theLine;
}
else
{
thePExp += "+" + theLine;
}
}
}
return thePExp.Substring(1) + theNExp;
}
/// <summary>
/// 对数组进行全排列
/// </summary>
/// <param name="lsArray">要进行全排列的数组</param>
/// <param name="begin">进行全排列的開始下标</param>
/// <param name="end">进行全排列的结束下标</param>
public static void FullPermutation(List<string> lsArray, int begin, int end, List<string> Result)
{
if (begin == end)
{
string theLine = "";
for (int i = 0; i <= end; i++)
{ theLine += "," + lsArray[i];
}
Result.Add(theLine.Substring(1));
} for (int i = begin; i <= end; i++)
{
Swap(lsArray, begin, i);
FullPermutation(lsArray, begin + 1, end, Result);
Swap(lsArray, begin, i);
} }
/// <summary>
/// 交换数组中的下标为x,y的值
/// </summary>
/// <param name="lsArray">该数组</param>
/// <param name="x"></param>
/// <param name="y"></param>
private static void Swap(List<string> lsArray, int x, int y)
{
string t = lsArray[x];
lsArray[x] = lsArray[y];
lsArray[y] = t;
}
/// <summary>
/// 化三角法行列式计算,
/// </summary>
/// <param name="Determinants">N阶行列式</param>
/// <returns>计算结果</returns>
public static decimal CalcDeterminant(decimal[,] Determinants)
{
int theSign = 1;//正负符号。假设须要变换,将记录变换后的符号.
int theN = Determinants.GetLength(0);
//从第1列到第theN-1列
for (int i = 0; i < theN - 1; i++)
{
//从第theN-1行到第i+1行。将D[j,i]依次变为0
for (int j = theN - 1; j > i; j--)
{
//假设为当前值为0,则不处理,继续处理上一行
if (Determinants[j, i] == 0)
{
continue;
} //假设[j,i]的上一行[j-1, i]的值为0则交换
if (Determinants[j - 1, i] == 0)
{
//每次交换,行列式的值大小不变。符号取反
theSign = 0 - theSign;
for (int k = 0; k < theN; k++)
{
decimal theTmpDec = Determinants[j, k];
Determinants[j, k] = Determinants[j - 1, k];
Determinants[j - 1, k] = theTmpDec;
}
}
else
{
//将当前行减去上一行与theRate的积。 var theRate = Determinants[j, i] / Determinants[j - 1, i];
for (int k = 0; k < theN; k++)
{
Determinants[j, k] = Determinants[j, k] - Determinants[j - 1, k] * theRate;
}
}
}
}
//结果为对角线上的元素的乘积,注意符号的处理。
decimal theRetDec = theSign;
for (int i = 0; i < theN; i++)
{
theRetDec *= Determinants[i, i];
}
return theRetDec;
}
}