本文实例讲述了C#计算矩阵的秩的方法。分享给大家供大家参考。具体如下:
1.代码思路
计算矩阵的秩,即把矩阵进行行初等变换,得出的行最简矩阵的非零行数。过程如下
1)将矩阵各行按第一个非零元素出现的位置升序排列(Operation1函数)
2)查看矩阵是否为行最简矩阵(isFinished函数),是则到第6步,不是则到第3步
3)如果有两行第一个非零元素出现的位置相同,则做消法变换,让下面行的第一个非零元素位置后移(Operation2函数)
4)将矩阵各行按第一个非零元素出现的位置升序排列(Operation1函数)
5)返回第2步
6)判断误差,对趋近与0的元素(如1E-5)按0处理,以免在第7步误判(Operation3函数)
7)统计非零行的数目(Operation4函数),即为矩阵的秩
2.函数代码
(注:本段代码只实现了一个思路,可能并不是该问题的最优解)
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
/// <summary>
/// 计算矩阵的秩
/// </summary>
/// <param name="matrix">矩阵</param>
/// <returns></returns>
private static int Rank(double[][] matrix)
{
//matrix为空则直接默认已经是最简形式
if (matrix == null || matrix.Length == 0) return 0;
//复制一个matrix到copy,之后因计算需要改动矩阵时并不改动matrix本身
double[][] copy = new double[matrix.Length][];
for (int i = 0; i < copy.Length; i++)
{
copy[i] = new double[matrix[i].Length];
}
for (int i = 0; i < matrix.Length; i++)
{
for (int j = 0; j < matrix[0].Length; j++)
{
copy[i][j] = matrix[i][j];
}
}
//先以最左侧非零项的位置进行行排序
Operation1(copy);
//循环化简矩阵
while (!isFinished(copy))
{
Operation2(copy);
Operation1(copy);
}
//过于趋近0的项,视作0,减小误差
Operation3(copy);
//行最简矩阵的秩即为所求
return Operation4(matrix);
}
/// <summary>
/// 判断矩阵是否变换到最简形式(非零行数达到最少)
/// </summary>
/// <param name="matrix"></param>
/// <returns>true:</returns>
private static bool isFinished(double[][] matrix)
{
//统计每行第一个非零元素的出现位置
int[] counter = new int[matrix.Length];
for (int i = 0; i < matrix.Length; i++)
{
for (int j = 0; j < matrix[i].Length; j++)
{
if (matrix[i][j] == 0)
{
counter[i]++;
}
else break;
}
}
//后面行的非零元素出现位置必须在前面行的后面,全零行除外
for (int i = 1; i < counter.Length; i++)
{
if (counter[i] <= counter[i - 1] && counter[i] != matrix[0].Length)
{
return false;
}
}
return true;
}
/// <summary>
/// 排序(按左侧最前非零位位置自上而下升序排列)
/// </summary>
/// <param name="matrix">矩阵</param>
private static void Operation1(double[][] matrix)
{
//统计每行第一个非零元素的出现位置
int[] counter = new int[matrix.Length];
for (int i = 0; i < matrix.Length; i++)
{
for (int j = 0; j < matrix[i].Length; j++)
{
if (matrix[i][j] == 0)
{
counter[i]++;
}
else break;
}
}
//按每行非零元素的出现位置升序排列
for (int i = 0; i < counter.Length; i++)
{
for (int j = i; j < counter.Length; j++)
{
if(counter[i]>counter[j])
{
double[] dTemp = matrix[i];
matrix[i] = matrix[j];
matrix[j] = dTemp;
}
}
}
}
/// <summary>
/// 行初等变换(左侧最前非零位位置最靠前的行,只保留一个)
/// </summary>
/// <param name="matrix">矩阵</param>
private static void Operation2(double[][] matrix)
{
//统计每行第一个非零元素的出现位置
int[] counter = new int[matrix.Length];
for (int i = 0; i < matrix.Length; i++)
{
for (int j = 0; j < matrix[i].Length; j++)
{
if (matrix[i][j] == 0)
{
counter[i]++;
}
else break;
}
}
for (int i = 1; i < counter.Length; i++)
{
if (counter[i] == counter[i - 1] && counter[i] != matrix[0].Length)
{
double a = matrix[i - 1][counter[i - 1]];
double b = matrix[i][counter[i]]; //counter[i]==counter[i-1]
matrix[i][counter[i]] = 0;
for (int j = counter[i] + 1; j < matrix[i].Length; j++)
{
double c = matrix[i - 1][j];
matrix[i][j] -= (c * b / a);
}
break;
}
}
}
/// <summary>
/// 将和0非常接近的数字视为0
/// </summary>
/// <param name="matrix"></param>
private static void Operation3(double[][] matrix)
{
for (int i = 0; i < matrix.Length; i++)
{
for (int j = 0; j < matrix[0].Length; j++)
{
if (Math.Abs(matrix[i][j]) <= 0.00001)
{
matrix[i][j] = 0;
}
}
}
}
/// <summary>
/// 计算行最简矩阵的秩
/// </summary>
/// <param name="matrix"></param>
/// <returns></returns>
private static int Operation4(double[][] matrix)
{
int rank = -1;
bool isAllZero = true;
for (int i = 0; i < matrix.Length; i++)
{
isAllZero = true;
//查看当前行有没有0
for (int j = 0; j < matrix[0].Length; j++)
{
if (matrix[i][j] != 0)
{
isAllZero = false;
break;
}
}
//若第i行全为0,则矩阵的秩为i
if (isAllZero)
{
rank = i;
break;
}
}
//满秩矩阵的情况
if (rank == -1)
{
rank = matrix.Length;
}
return rank;
}
|
3.Main函数调用
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
static void Main(string[] args)
{
//示例矩阵1:秩为3
double[][] matrix1 = new double[][]
{
new double[] { 1, 1, 1 },
new double[] { 1, 1, 0 },
new double[] { 0, 1, 1 }
};
Console.WriteLine(Rank(matrix1));
//示例矩阵2:秩为3
double[][] matrix2 = new double[][]
{
new double[] { 3, 2, 0, 5, 0 },
new double[] { 3, -2, 3, 6, -1 },
new double[] { 2, 0, 1, 5, -3 },
new double[] { 1, 6, -4, -1, 4 }
};
Console.WriteLine(Rank(matrix2));
//示例矩阵3:秩为3
double[][] matrix3 = new double[][]
{
new double[] { 2, 3, 1, -3, -7 },
new double[] { 1, 2, 0, -2, -4 },
new double[] { 3, -2, 8, 3, 0 },
new double[] { 2, -3, 7, 4, 3 }
};
Console.WriteLine(Rank(matrix3));
Console.ReadLine();
}
|
4.执行结果

希望本文所述对大家的C#程序设计有所帮助。








发表评论
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。