前段时间做项目,将关于矩阵的一些操作封装了一个类,共享一下。
主要功能包括:计算矩阵的行列式、矩阵的最大特征值和它所对应的特征向量、矩阵的逆、矩阵的一致性指标。
using System;
using System.Collections.Generic;
using System.Text;
namespace Car.systemClass
{
public class MatrixLab
{
private static int N;
private double eps;
private double[,] A ;
private double[] U ;
private double[] V;
private int[] Z;
//计算1000次平的均随机一致性指标
public static double[] RI ={ 0, 0, 0.52, 0.89, 1.12, 1.26, 1.36, 1.41, 1.46, 1.49 };
/// <summary>
/// 构造函数
/// </summary>
/// <param name="n">矩阵的维长度</param>
/// <param name="e">求解精度</param>
/// <param name="a">矩阵对象</param>
public MatrixLab(int n, double e, double[,] a)
{
N = n;
eps = e;
A = new double[N, N];
U = new double[N];
V = new double[N];
buildMatrix(a);
}
/// <summary>
/// 返回和设置矩阵的维长度
/// </summary>
public int NValue
{
get
{
return N;
}
set
{
N = value;
}
}
/// <summary>
/// 返回和设置求解精度
/// </summary>
public double Eps
{
get
{
return eps;
}
set
{
eps = value;
}
}
/// <summary>
/// 构造一个方阵
/// </summary>
/// <param name="a">输入该方阵</param>
private void buildMatrix(double[,] a)
{
if (a.Rank == A.Rank)
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
A[i, j] = a[i, j];
}
}
}
}
/// <summary>
/// 求一个一维数组中的最大值
/// </summary>
/// <param name="W">一个一维数组</param>
/// <returns>最大值</returns>
private double maxValue(params double[] W)
{
double tmp = 0;
if (W.Length != 0)
tmp = W[0];
for (int i = 1; i < W.Length; i++)
{
if (W[i] > tmp)
tmp = W[0];
}
return tmp;
}
/// <summary>
/// 使用幂法求一个方阵的最大特征值和它所对应的特征向量
/// </summary>
/// <param name="W">最大特征值所对应的特征向量</param>
/// <param name="max">最大特征值</param>
/// /// <param name="round">结果小数点后的尾数长度(精度)</param>
public void returnResult(ref double[]W,ref double max)
{
int i = 0;
for (i = 0; i < N; i++)
{
U[i] = 1;
}
int k = 1;
double m0, mk = 0;
m0 = maxValue(U);
for (i = 0; i < N; i++)
{
U[i] = 1;
}
m0 = maxValue(U);
while (true)
{
for (i = 0; i < N; i++)
{
V[i] = U[i] / m0;
}
for (i = 0; i < N; i++)
{
double sum = 0;
for (int j = 0; j < N; j++)
{
sum += A[i, j] * V[j];
}
U[i] = sum;
}
mk = maxValue(U);
if (Math.Abs(mk - m0) >= eps)
{
if ((Math.Abs(mk - m0) / (1 + mk)) >= eps)
{
m0 = mk;
k++;
}
else
break;
}
else
break;
}
if (Math.Abs(mk - m0) < eps || (Math.Abs(mk - m0) >= eps && (Math.Abs(mk - m0) / (1 + mk)) < eps))
{
W =V;
max = mk;
}
}
public void returnResult2(ref double[] W, ref double max)
{
int i = 0;
for (i = 0; i < N; i++)
{
U[i] = 1;
}
int k = 1;
double m0, mk = 0;
m0 = maxValue(U);
for (i = 0; i < N; i++)
{
U[i] = 1;
}
m0 = maxValue(U);
while (true)
{
for (i = 0; i < N; i++)
{
V[i] = U[i] / m0;
}
for (i = 0; i < N; i++)
{
double sum = 0;
for (int j = 0; j < N; j++)
{
sum += A[i, j] * V[j];
}
U[i] = sum;
}
mk = maxValue(U);
if (Math.Abs(mk - m0) >= eps)
{
if ((Math.Abs(mk - m0) / (1 + mk)) >= eps)
{
m0 = mk;
k++;
}
else
break;
}
else
break;
}
if (Math.Abs(mk - m0) < eps || (Math.Abs(mk - m0) >= eps && (Math.Abs(mk - m0) / (1 + mk)) < eps))
{
W = V;
max = mk;
}
double SUM = 0;
for (i = 0; i < W.Length; i++)
{
SUM += W[i];
}
for (i = 0; i < W.Length; i++)
{
W[i] = W[i] / SUM;
}
}
/// <summary>
/// 求矩阵的逆
/// </summary>
/// <returns>原矩阵的逆矩阵</returns>
public double[,] invertMatrix()
{
int i = 0;
Z = new int[N];
for (i = 0; i < N; i++)
{
Z[i] = i;
}
int K = 0;
int L = 0;
double D = 0;
double maxA = 0;
int t = 0;
double Ck = 0;
while (K != N)
{
maxA = Math.Abs(A[K, K]);
L = K;
i = K + 1;
while (i != N)
{
if (Math.Abs(A[i, K]) > maxA)
{
maxA = Math.Abs(A[i, K]);
L = i;
}
i++;
}
i = 0;
D = A[L, K];
Z[K] = L;
if (D == 0)
break;
int j = 0;
if (L != K)
{
for (j = 0; j < N; j++)
{
double tmp = A[K, j];
A[K, j] = A[L, j];
A[L, j] = tmp;
}
}
Ck = 1 / A[K, K];
A[K, K] = Ck;
for (j = 0; j < N; j++)
{
if (j != K)
A[K, j] = A[K, j] * Ck;
}
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
if (i != K && j != K)
A[i, j] = A[i, j] - A[i, K] * A[K, j];
}
}
for (i = 0; i < N; i++)
{
if (i != K)
A[i, K] = -A[i, K] * Ck;
}
K++;
}
K = N - 2;
while (K >= 0)
{
t = Z[K];
if (t != K)
for (i = 0; i < N; i++)
{
double tmp = A[i, K];
A[i, K] = A[i, t];
A[i, t] = tmp;
}
K--;
}
return A;
}
/*函数介绍:输入一个行列式,用递归的方法,以行列式的行序为主序求行列式的值
输入参数:const int a[][N] :一个以二维数组形式存储的行列式
int n:行列式的阶数
输出参数:无
返回值: int :行列式的值
*/
/// <summary>
/// 输入一个行列式,用递归的方法,以行列式的行序为主序求行列式的值
/// </summary>
/// <param name="a">一个以二维数组形式存储的行列式</param>
/// <param name="n">行列式的阶数</param>
/// <returns>行列式的值</returns>
public double HLS(double[,] a, int n)
{
if (n == 1) //如果行列式的阶数为1,直接返回其值
{
return a[0, 0];
}
else //否则按照求代数余子式的方法,采用递归方式求行列式的值
{
double sum = 0; //用来存储当前行列式(可能是上一层行列式的余子式)的值
for (int i = 0; i < n; i++)//以行列式的行序为主序求行列式的值
{
double[,] Y = new double[N, N]; //存储行列式当前元素的余子式
YZS(Y, a, n, i); //求行列式当前元素的余子式
int xs = (i % 2 == 0) ? 1 : -1; //计算行列式当前元素的代数余子式的系数
sum += xs * a[i, 0] * HLS(Y, n - 1);//累积当前行列式的值
}
return sum;
}
}
/*函数介绍:输入一个行列式及其第0列第a-r行元素,求该元素的余子式
输入参数:const int a[][N] :一个以二维数组形式存储的行列式
int n:行列式的阶数
int a_r:元素的行号(列号默认为0)
输出参数:int Y[][N]:该元素的余子式
返回值: void
*/
/// <summary>
/// 输入一个行列式及其第0列第a-r行元素,求该元素的余子式
/// </summary>
/// <param name="Y">该元素的余子式</param>
/// <param name="a">一个以二维数组形式存储的行列式</param>
/// <param name="len">行列式的阶数</param>
/// <param name="a_r">元素的行号(列号默认为0)</param>
private void YZS(double[,] Y, double[,] a, int len, int a_r)
{
int r = 0;//r,c用来填充余子式的元素值
int c = 0;
for (int i = 0; i < len; i++)
{
if (i != a_r)
{
for (int j = 1; j < len; j++)
{
Y[r, c++] = a[i, j];
}
r++;
c = 0;
}
}
}
/// <summary>
/// 计算一致性指标CI
/// </summary>
/// <param name="lamda">n阶矩阵的最大特征值</param>
/// <param name="n">矩阵的阶数</param>
/// <returns>一致性指标CI的值</returns>
public static double CI(double lamda, int n)
{
if (n > 1 && lamda >= n)
return (lamda - n) / (n - 1);
else
return -1;
}
}
}