1.1.33 #
解答 #
这里矩阵使用交错数组实现(方便取行向量),不是普通的二维数组。
矩阵和矩阵、矩阵和向量、向量和矩阵都使用行向量点乘列向量的方式计算。
代码 #
public class Matrix
{
/// <summary>
/// 计算两个向量的点积
/// </summary>
/// <param name="x">需要点乘的向量</param>
/// <param name="y">需要点乘的另一个向量</param>
/// <returns>返回点乘的结果</returns>
/// <exception cref="FormatException"></exception>
public static double Dot(double[] x, double[] y)
{
//确保两向量等长
if (x.Length != y.Length)
{
throw new FormatException("the length of two vectors must be equal");
}
//点乘
double result = 0;
for (int i = 0; i < x.Length; ++i)
{
result += x[i] * y[i];
}
return result;
}
/// <summary>
/// 计算两个矩阵相乘的结果,返回一个矩阵
/// </summary>
/// <param name="a">用交错数组表示的 m * p 矩阵</param>
/// <param name="b">用交错数组表示的 p * n 矩阵</param>
/// <returns>返回 m * n 的矩阵</returns>
/// <exception cref="FormatException"></exception>
/// <example>
/// a = {(1,2,3),(4,5,6)}
/// b = {(1,4),(2,5),(3,6)}
/// Mult(a, b) = {(14,32),(32,77)}
/// </example>
public static double[][] Mult(double[][] a, double[][] b)
{
if (a[0].Length != b.GetLength(0))
{
throw new FormatException("a's column number must be equal to b's row number");
}
int m = a.GetLength(0);
int n = b[0].Length;
int p = a[0].Length;
double[][] result = new double[m][];
for (int i = 0; i < m; ++i)
{
double[] resultrow = new double[n];
for (int j = 0; j < n; ++j)
{
//result[i][j] = 行向量 a[i] 与列向量 b[j] 的点积
double[] row = a[i];
double[] col = new double[p];
//取得列向量
for (int k = 0; k < p; ++k)
{
col[k] = b[k][j];
}
//点积
resultrow[j] = Dot(row, col);
}
result[i] = resultrow;
}
return result;
}
/// <summary>
/// 将一个矩阵转置
/// </summary>
/// <param name="a">待转置的矩阵</param>
/// <returns>返回转置后的数组</returns>
public static double[][] Transpose(double[][] a)
{
double[][] trans = new double[a[0].Length][];
for (int i = 0; i < a[0].Length; ++i)
{
double[] row = new double[a.GetLength(0)];
for (int j = 0; j < a.GetLength(0); ++j)
{
row[j] = a[j][i];
}
trans[i] = row;
}
return trans;
}
/// <summary>
/// 计算矩阵与向量的乘积
/// </summary>
/// <param name="a">左乘的矩阵</param>
/// <param name="x">列向量</param>
/// <returns>返回一个向量</returns>
/// <exception cref="FormatException"></exception>
public static double[] Mult(double[][] a, double[] x)
{
if (a[0].Length != x.Length)
{
throw new FormatException("a's column number must be equal to x's length");
}
double[] result = new double[a.GetLength(0)];
for (int i = 0; i < a.GetLength(0); ++i)
{
result[i] = Dot(a[i], x);
}
return result;
}
/// <summary>
/// 计算向量与矩阵的乘积
/// </summary>
/// <param name="x">行向量</param>
/// <param name="a">矩阵</param>
/// <returns>返回一个向量</returns>
/// <exception cref="FormatException"></exception>
public static double[] Mult(double[] x, double[][] a)
{
if (a.GetLength(0) != x.Length)
{
throw new FormatException("a's column number must be equal to x's length");
}
double[] result = new double[a[0].Length];
for (int i = 0; i < a[0].Length; ++i)
{
double[] colVector = new double[a.GetLength(0)];
for (int j = 0; j < colVector.Length; ++j)
{
colVector[j] = a[j][i];
}
result[i] = Dot(x, colVector);
}
return result;
}
/// <summary>
/// 在控制台上输出矩阵
/// </summary>
/// <param name="a">需要输出的矩阵</param>
public static void PrintMatrix(double[][] a)
{
for (int i = 0; i < a.GetLength(0); ++i)
{
for (int j = 0; j < a[i].Length; ++j)
{
Console.Write($"\t{a[i][j]}");
}
Console.Write("\n");
}
}
/// <summary>
/// 在控制台上输出一行向量
/// </summary>
/// <param name="a">需要输出的向量</param>
public static void PrintVector(double[] a)
{
for (int i = 0; i < a.Length; ++i)
{
Console.Write($"\t{a[i]}");
}
Console.Write("\n");
}
}