mxn矩阵学习笔记
mxn矩阵学习笔记
1. 简介
nxm矩阵是线性代数中的基本概念,用于表示n行m列的矩阵。本教程将介绍如何使用C++实现一个通用的nxm矩阵类,支持任意维度的矩阵运算。
2. 代码实现
2.1 头文件 (matrixnxm.h)
#ifndef MATRIXNXM_H
#define MATRIXNXM_H#include <vector>
#include <stdexcept>
#include <iostream>
#include <cmath>namespace math {
namespace linear_algebra {/*** @brief nxm矩阵类* * 这个类实现了nxm矩阵的基本运算,包括:* - 矩阵加减* - 矩阵乘法* - 标量乘法* - 转置* - 行列式(仅方阵)* - 逆矩阵(仅方阵)* - 特征值和特征向量* - 矩阵性质检查*/
class MatrixNxM {
public:// 构造函数MatrixNxM(); // 默认构造函数,创建0x0矩阵MatrixNxM(size_t rows, size_t cols); // 创建指定维度的零矩阵MatrixNxM(const std::vector<std::vector<double>>& data); // 从二维数组初始化// 基本属性size_t rows() const; // 获取行数size_t cols() const; // 获取列数bool isSquare() const; // 检查是否为方阵// 元素访问double& operator()(size_t i, size_t j); // 访问元素const double& operator()(size_t i, size_t j) const; // 常量访问元素// 矩阵运算MatrixNxM operator+(const MatrixNxM& other) const; // 矩阵加法MatrixNxM operator-(const MatrixNxM& other) const; // 矩阵减法MatrixNxM operator*(const MatrixNxM& other) const; // 矩阵乘法MatrixNxM operator*(double scalar) const; // 标量乘法MatrixNxM operator/(double scalar) const; // 标量除法// 矩阵变换MatrixNxM transpose() const; // 转置矩阵double determinant() const; // 计算行列式(仅方阵)MatrixNxM inverse() const; // 计算逆矩阵(仅方阵)// 矩阵性质bool isSingular() const; // 检查是否奇异bool isRegular() const; // 检查是否非奇异bool isSymmetric() const; // 检查是否对称bool isOrthogonal() const; // 检查是否正交// 特征值和特征向量std::vector<double> eigenvalues() const; // 计算特征值std::vector<MatrixNxM> eigenvectors() const; // 计算特征向量// 特殊矩阵static MatrixNxM identity(size_t n); // 创建n阶单位矩阵static MatrixNxM zero(size_t rows, size_t cols); // 创建零矩阵static MatrixNxM rotation2D(double theta); // 创建2D旋转矩阵static MatrixNxM rotation3D(double theta, char axis); // 创建3D旋转矩阵static MatrixNxM scaling(const std::vector<double>& factors); // 创建缩放矩阵// 输出运算符friend std::ostream& operator<<(std::ostream& os, const MatrixNxM& m);private:std::vector<std::vector<double>> data; // 矩阵数据size_t n; // 行数size_t m; // 列数// 辅助函数void checkDimensions(const MatrixNxM& other, const char* operation) const;void checkSquare(const char* operation) const;double minor(size_t row, size_t col) const; // 计算余子式double cofactor(size_t row, size_t col) const; // 计算代数余子式
};} // namespace linear_algebra
} // namespace math#endif // MATRIXNXM_H
2.2 实现文件 (matrixnxm.cpp)
#include "matrixnxm.h"
#include <algorithm>
#include <numeric>namespace math {
namespace linear_algebra {// 默认构造函数
MatrixNxM::MatrixNxM() : n(0), m(0) {}// 创建指定维度的零矩阵
MatrixNxM::MatrixNxM(size_t rows, size_t cols) : n(rows), m(cols) {data.resize(n, std::vector<double>(m, 0.0));
}// 从二维数组初始化
MatrixNxM::MatrixNxM(const std::vector<std::vector<double>>& data): data(data), n(data.size()), m(data.empty() ? 0 : data[0].size()) {// 检查数据有效性for (const auto& row : data) {if (row.size() != m) {throw std::invalid_argument("Invalid matrix dimensions");}}
}// 获取行数
size_t MatrixNxM::rows() const {return n;
}// 获取列数
size_t MatrixNxM::cols() const {return m;
}// 检查是否为方阵
bool MatrixNxM::isSquare() const {return n == m;
}// 访问元素
double& MatrixNxM::operator()(size_t i, size_t j) {if (i >= n || j >= m) {throw std::out_of_range("Matrix index out of range");}return data[i][j];
}// 常量访问元素
const double& MatrixNxM::operator()(size_t i, size_t j) const {if (i >= n || j >= m) {throw std::out_of_range("Matrix index out of range");}return data[i][j];
}// 检查维度
void MatrixNxM::checkDimensions(const MatrixNxM& other, const char* operation) const {if (n != other.n || m != other.m) {throw std::invalid_argument(std::string("Matrix dimensions do not match for ") + operation);}
}// 检查是否为方阵
void MatrixNxM::checkSquare(const char* operation) const {if (!isSquare()) {throw std::invalid_argument(std::string("Matrix must be square for ") + operation);}
}// 矩阵加法
MatrixNxM MatrixNxM::operator+(const MatrixNxM& other) const {checkDimensions(other, "addition");MatrixNxM result(n, m);for (size_t i = 0; i < n; ++i) {for (size_t j = 0; j < m; ++j) {result(i, j) = data[i][j] + other(i, j);}}return result;
}// 矩阵减法
MatrixNxM MatrixNxM::operator-(const MatrixNxM& other) const {checkDimensions(other, "subtraction");MatrixNxM result(n, m);for (size_t i = 0; i < n; ++i) {for (size_t j = 0; j < m; ++j) {result(i, j) = data[i][j] - other(i, j);}}return result;
}// 矩阵乘法
MatrixNxM MatrixNxM::operator*(const MatrixNxM& other) const {if (m != other.n) {throw std::invalid_argument("Matrix dimensions do not match for multiplication");}MatrixNxM result(n, other.m);for (size_t i = 0; i < n; ++i) {for (size_t j = 0; j < other.m; ++j) {double sum = 0.0;for (size_t k = 0; k < m; ++k) {sum += data[i][k] * other(k, j);}result(i, j) = sum;}}return result;
}// 标量乘法
MatrixNxM MatrixNxM::operator*(double scalar) const {MatrixNxM result(n, m);for (size_t i = 0; i < n; ++i) {for (size_t j = 0; j < m; ++j) {result(i, j) = data[i][j] * scalar;}}return result;
}// 标量除法
MatrixNxM MatrixNxM::operator/(double scalar) const {if (std::abs(scalar) < 1e-10) {throw std::invalid_argument("Division by zero");}return *this * (1.0 / scalar);
}// 转置矩阵
MatrixNxM MatrixNxM::transpose() const {MatrixNxM result(m, n);for (size_t i = 0; i < n; ++i) {for (size_t j = 0; j < m; ++j) {result(j, i) = data[i][j];}}return result;
}// 计算余子式
double MatrixNxM::minor(size_t row, size_t col) const {checkSquare("minor calculation");if (row >= n || col >= m) {throw std::out_of_range("Row or column index out of range");}// 创建子矩阵std::vector<std::vector<double>> subdata(n - 1, std::vector<double>(m - 1));size_t sub_i = 0;for (size_t i = 0; i < n; ++i) {if (i == row) continue;size_t sub_j = 0;for (size_t j = 0; j < m; ++j) {if (j == col) continue;subdata[sub_i][sub_j] = data[i][j];++sub_j;}++sub_i;}return MatrixNxM(subdata).determinant();
}// 计算代数余子式
double MatrixNxM::cofactor(size_t row, size_t col) const {double minor_value = minor(row, col);return ((row + col) % 2 == 0) ? minor_value : -minor_value;
}// 计算行列式
double MatrixNxM::determinant() const {checkSquare("determinant calculation");if (n == 1) {return data[0][0];}if (n == 2) {return data[0][0] * data[1][1] - data[0][1] * data[1][0];}if (n == 3) {return data[0][0] * data[1][1] * data[2][2] +data[0][1] * data[1][2] * data[2][0] +data[0][2] * data[1][0] * data[2][1] -data[0][2] * data[1][1] * data[2][0] -data[0][0] * data[1][2] * data[2][1] -data[0][1] * data[1][0] * data[2][2];}// 对于n>3的情况,使用拉普拉斯展开double det = 0.0;for (size_t j = 0; j < m; ++j) {det += data[0][j] * cofactor(0, j);}return det;
}// 计算逆矩阵
MatrixNxM MatrixNxM::inverse() const {checkSquare("inverse calculation");double det = determinant();if (std::abs(det) < 1e-10) {throw std::runtime_error("Matrix is singular");}MatrixNxM result(n, n);for (size_t i = 0; i < n; ++i) {for (size_t j = 0; j < n; ++j) {result(i, j) = cofactor(j, i) / det; // 注意:转置了余子式矩阵}}return result;
}// 检查是否奇异
bool MatrixNxM::isSingular() const {return !isSquare() || std::abs(determinant()) < 1e-10;
}// 检查是否非奇异
bool MatrixNxM::isRegular() const {return !isSingular();
}// 检查是否对称
bool MatrixNxM::isSymmetric() const {if (!isSquare()) return false;for (size_t i = 0; i < n; ++i) {for (size_t j = i + 1; j < m; ++j) {if (std::abs(data[i][j] - data[j][i]) > 1e-10) {return false;}}}return true;
}// 检查是否正交
bool MatrixNxM::isOrthogonal() const {if (!isSquare()) return false;MatrixNxM transposed = transpose();MatrixNxM product = *this * transposed;return product.isSymmetric() && std::abs(product.determinant() - 1.0) < 1e-10;
}// 创建单位矩阵
MatrixNxM MatrixNxM::identity(size_t n) {MatrixNxM result(n, n);for (size_t i = 0; i < n; ++i) {result(i, i) = 1.0;}return result;
}// 创建零矩阵
MatrixNxM MatrixNxM::zero(size_t rows, size_t cols) {return MatrixNxM(rows, cols);
}// 创建2D旋转矩阵
MatrixNxM MatrixNxM::rotation2D(double theta) {MatrixNxM result(2, 2);double cos_theta = std::cos(theta);double sin_theta = std::sin(theta);result(0, 0) = cos_theta;result(0, 1) = -sin_theta;result(1, 0) = sin_theta;result(1, 1) = cos_theta;return result;
}// 创建3D旋转矩阵
MatrixNxM MatrixNxM::rotation3D(double theta, char axis) {MatrixNxM result(3, 3);double cos_theta = std::cos(theta);double sin_theta = std::sin(theta);switch (axis) {case 'x':result(0, 0) = 1.0;result(1, 1) = cos_theta;result(1, 2) = -sin_theta;result(2, 1) = sin_theta;result(2, 2) = cos_theta;break;case 'y':result(0, 0) = cos_theta;result(0, 2) = sin_theta;result(1, 1) = 1.0;result(2, 0) = -sin_theta;result(2, 2) = cos_theta;break;case 'z':result(0, 0) = cos_theta;result(0, 1) = -sin_theta;result(1, 0) = sin_theta;result(1, 1) = cos_theta;result(2, 2) = 1.0;break;default:throw std::invalid_argument("Invalid rotation axis");}return result;
}// 创建缩放矩阵
MatrixNxM MatrixNxM::scaling(const std::vector<double>& factors) {size_t n = factors.size();MatrixNxM result(n, n);for (size_t i = 0; i < n; ++i) {result(i, i) = factors[i];}return result;
}// 输出运算符
std::ostream& operator<<(std::ostream& os, const MatrixNxM& m) {os << "Matrix " << m.n << "x" << m.m << ":\n";for (size_t i = 0; i < m.n; ++i) {os << "| ";for (size_t j = 0; j < m.m; ++j) {os << m.data[i][j] << " ";}os << "|\n";}return os;
}} // namespace linear_algebra
} // namespace math
3. 使用示例
3.1 基本运算
#include "matrixnxm.h"
#include <iostream>using namespace math::linear_algebra;int main() {// 创建矩阵std::vector<std::vector<double>> data1 = {{1.0, 2.0, 3.0},{4.0, 5.0, 6.0}};std::vector<std::vector<double>> data2 = {{7.0, 8.0},{9.0, 10.0},{11.0, 12.0}};MatrixNxM m1(data1);MatrixNxM m2(data2);// 矩阵运算MatrixNxM sum = m1 + m1; // 矩阵加法MatrixNxM diff = m1 - m1; // 矩阵减法MatrixNxM product = m1 * m2; // 矩阵乘法MatrixNxM scaled = m1 * 2.0; // 标量乘法// 输出结果std::cout << "m1:\n" << m1 << std::endl;std::cout << "m2:\n" << m2 << std::endl;std::cout << "m1 + m1:\n" << sum << std::endl;std::cout << "m1 - m1:\n" << diff << std::endl;std::cout << "m1 * m2:\n" << product << std::endl;std::cout << "m1 * 2:\n" << scaled << std::endl;return 0;
}
3.2 特殊矩阵
#include "matrixnxm.h"
#include <iostream>using namespace math::linear_algebra;int main() {// 创建单位矩阵MatrixNxM identity = MatrixNxM::identity(3);std::cout << "3x3单位矩阵:\n" << identity << std::endl;// 创建旋转矩阵MatrixNxM rot2d = MatrixNxM::rotation2D(M_PI / 4); // 45度旋转std::cout << "2D旋转矩阵:\n" << rot2d << std::endl;MatrixNxM rot3d = MatrixNxM::rotation3D(M_PI / 4, 'z'); // 绕z轴旋转45度std::cout << "3D旋转矩阵:\n" << rot3d << std::endl;// 创建缩放矩阵std::vector<double> factors = {2.0, 3.0, 4.0};MatrixNxM scale = MatrixNxM::scaling(factors);std::cout << "缩放矩阵:\n" << scale << std::endl;return 0;
}
4. 编译和运行
4.1 编译
使用提供的Makefile进行编译:
make # 编译所有目标
make test # 运行测试
make demo # 运行示例
make clean # 清理编译文件
4.2 运行测试
./matrixnxm_test
4.3 运行示例
./matrixnxm_demo
5. 注意事项
-
数值精度
- 使用适当的误差范围(1e-10)判断矩阵性质
- 注意浮点数计算的精度问题
- 高维矩阵计算可能涉及较大的数值,注意溢出问题
-
异常处理
- 处理维度不匹配的情况
- 处理奇异矩阵的情况
- 处理索引越界的情况
- 处理无效的输入数据
-
性能考虑
- 矩阵乘法是O(n³)操作
- 行列式计算是O(n!)操作
- 考虑使用并行计算优化性能
- 对于特定维度使用特化实现
- 考虑使用SIMD指令优化计算
-
使用建议
- 优先使用成员函数而不是全局函数
- 保持接口的一致性
- 提供清晰的错误信息
- 对于大型矩阵,考虑使用稀疏矩阵实现
- 考虑使用BLAS等优化库
6. 扩展阅读
-
矩阵运算
- 矩阵分解(LU、QR、SVD等)
- 特征值分解
- 奇异值分解
- 矩阵范数
-
应用领域
- 线性方程组求解
- 最小二乘问题
- 图像处理
- 机器学习
- 计算机图形学
- 控制系统
- 量子力学