赞
踩
阅读这篇文章需要掌握C++类的知识以及线性代数的知识,如果有疑问,可在文章下方评论,作者会尽快回复;本文是在作者阅读了平冈和幸的程序员的数学3:线性代数之后而写,在代码设计上借鉴了书中的方法。
希望这些代码能够帮助你更好地理解线性代数里提到的矩阵运算,笔者所写的矩阵运算代码,都是初学C++时实现的,并不具有工程应用的价值;真诚的希望读者能够使用更好的矩阵运算库,比如Eigen,OpenCV等,笔者对这两个C++库的理解也是比较深入的;当然,如果读者还了解Python的话,笔者建议学习numpy,numpy的Cpp代码可以在Github上搜索NumCpp。
初写这份代码时,笔者才刚入C++,如今笔者将在github上上传新的矩阵运算代码NANAhttps://github.com/YuruTu/NANA
相关文档见地址NANA doxygen生成文档
https://yurutu.github.io/NANA/files.html
具体实现的矩阵功能有:
最初版代码及其使用
利用C++的类实现矩阵的运算,可实现矩阵的+-*运算,以及用高斯消去法求解线性方程组Ax=b
2018/10/13新增功能 矩阵的行列变换 高斯消元法得到上三角矩阵
2018/12/9实现矩阵的逆运算等
预编译头文件
pch.h
- #ifndef PCH_H
- #define PCH_H
- #include <cmath>
- #include <iostream>
- #include <stdlib.h>
- #include <cmath>
- // TODO: 添加要在此处预编译的标头
-
- #endif //PCH_H
头文件.h
- /*
- author: cclplus
- date:2018/12/09
- if you think it is necessary to reward me,
- my alipay account number is 707101557@qq.com
- */
-
- #ifndef __MATRIX_CLL_H__
- #define __MATRIX_CCL_H__
- #include "pch.h"
-
- class Matrix {
- private:
- int rows_num, cols_num;
- double **p;
- void initialize();//初始化矩阵
-
- public:
- Matrix(int, int);
- Matrix(int, int, double);//预配分空间
- virtual ~Matrix();//析构函数应当是虚函数,除非此类不用做基类
- Matrix& operator=(const Matrix&);//矩阵的复制
- Matrix& operator=(double *);//将数组的值传给矩阵
- Matrix& operator+=(const Matrix&);//矩阵的+=操作
- Matrix& operator-=(const Matrix&);//-=
- Matrix& operator*=(const Matrix&);//*=
- Matrix operator*(const Matrix & m)const;
- static Matrix Solve(const Matrix&, const Matrix&);//求解线性方程组Ax=b
- void Show() const;//矩阵显示
- void swapRows(int, int);
- double det();//求矩阵的行列式
- double Point(int i, int j) const;
- static Matrix inv(Matrix);//求矩阵的逆矩阵
- static Matrix eye(int );//制造一个单位矩阵
- int row() const;
- int col() const;
- static Matrix T(const Matrix & m);//矩阵转置的实现,且不改变矩阵
- Matrix gaussianEliminate();//高斯消元法
- friend std::istream& operator>>(std::istream&, Matrix&);//实现矩阵的输入
- };
-
-
- #endif

头文件.cpp
- /*
- author: cclplus
- date : 2018 / 12 / 09
- if you think it is necessary to reward me,
- my alipay account number is 707101557@qq.com
- */
- #include "pch.h"
- #include "matrix.h"
- using std::endl;
- using std::cout;
- using std::istream;
- const double EPS = 1e-10;
- void Matrix::initialize() {//初始化矩阵大小
- p = new double*[rows_num];//分配rows_num个指针
- for (int i = 0; i < rows_num; ++i) {
- p[i] = new double[cols_num];//为p[i]进行动态内存分配,大小为cols
- }
- }
- //声明一个全0矩阵
- Matrix::Matrix(int rows, int cols)
- {
- rows_num = rows;
- cols_num = cols;
- initialize();
- for (int i = 0; i < rows_num; i++) {
- for (int j = 0; j < cols_num; j++) {
- p[i][j] = 0;
- }
- }
- }
- //声明一个值全部为value的矩阵
- Matrix::Matrix(int rows, int cols, double value)
- {
- rows_num = rows;
- cols_num = cols;
- initialize();
- for (int i = 0; i < rows_num; i++) {
- for (int j = 0; j < cols_num; j++) {
- p[i][j] = value;
- }
- }
- }
-
- //析构函数
- Matrix::~Matrix() {
- for (int i = 0; i < rows_num; ++i) {
- delete[] p[i];
- }
- delete[] p;
- }
- //实现矩阵的复制
- Matrix& Matrix::operator=(const Matrix& m)
- {
- if (this == &m) {
- return *this;
- }
-
- if (rows_num != m.rows_num || cols_num != m.cols_num) {
- for (int i = 0; i < rows_num; ++i) {
- delete[] p[i];
- }
- delete[] p;
-
- rows_num = m.rows_num;
- cols_num = m.cols_num;
- initialize();
- }
-
- for (int i = 0; i < rows_num; i++) {
- for (int j = 0; j < cols_num; j++) {
- p[i][j] = m.p[i][j];
- }
- }
- return *this;
- }
- //将数组的值传递给矩阵(要求矩阵的大小已经被声明过了)
- Matrix& Matrix::operator=(double *a){
- for(int i=0;i<rows_num;i++){
- for(int j=0;j<cols_num;j++){
- p[i][j]= *(a+i*cols_num+j);
- }
- }
- return *this;
- }
- //+=操作
- Matrix& Matrix::operator+=(const Matrix& m)
- {
- for (int i = 0; i < rows_num; i++) {
- for (int j = 0; j < cols_num; j++) {
- p[i][j] += m.p[i][j];
- }
- }
- return *this;
- }
- //实现-=
- Matrix& Matrix::operator-=(const Matrix& m)
- {
- for (int i = 0; i < rows_num; i++) {
- for (int j = 0; j < cols_num; j++) {
- p[i][j] -= m.p[i][j];
- }
- }
- return *this;
- }
- //实现*=
- Matrix& Matrix::operator*=(const Matrix& m)
- {
- Matrix temp(rows_num, m.cols_num);//若C=AB,则矩阵C的行数等于矩阵A的行数,C的列数等于B的列数。
- for (int i = 0; i < temp.rows_num; i++) {
- for (int j = 0; j < temp.cols_num; j++) {
- for (int k = 0; k < cols_num; k++) {
- temp.p[i][j] += (p[i][k] * m.p[k][j]);
- }
- }
- }
- *this = temp;
- return *this;
- }
- //实现矩阵的乘法
- Matrix Matrix::operator*(const Matrix & m)const{
- Matrix ba_M(rows_num,m.cols_num,0.0);
- for(int i=0;i<rows_num;i++){
- for(int j=0;j<m.cols_num;j++){
- for(int k=0;k<cols_num;k++){
- ba_M.p[i][j]+=(p[i][k]*m.p[k][j]);
- }
- }
- }
- return ba_M;
- }
-
- //解方程Ax=b
- Matrix Matrix::Solve(const Matrix &A, const Matrix &b)
- {
- //高斯消去法实现Ax=b的方程求解
- for (int i = 0; i < A.rows_num; i++) {
- if (A.p[i][i] == 0) {
-
- cout << "请重新输入" << endl;
- }
- for (int j = i + 1; j < A.rows_num; j++) {
- for (int k = i + 1; k < A.cols_num; k++) {
- A.p[j][k] -= A.p[i][k] * (A.p[j][i] / A.p[i][i]);
- if (abs(A.p[j][k]) < EPS)
- A.p[j][k] = 0;
- }
- b.p[j][0] -= b.p[i][0] * (A.p[j][i] / A.p[i][i]);
- if (abs(A.p[j][0]) < EPS)
- A.p[j][0] = 0;
- A.p[j][i] = 0;
- }
- }
-
- // 反向代换
- Matrix x(b.rows_num, 1);
- x.p[x.rows_num - 1][0] = b.p[x.rows_num - 1][0] / A.p[x.rows_num - 1][x.rows_num - 1];
- if (abs(x.p[x.rows_num - 1][0]) < EPS)
- x.p[x.rows_num - 1][0] = 0;
- for (int i = x.rows_num - 2; i >= 0; i--) {
- double sum = 0;
- for (int j = i + 1; j < x.rows_num; j++) {
- sum += A.p[i][j] * x.p[j][0];
- }
- x.p[i][0] = (b.p[i][0] - sum) / A.p[i][i];
- if (abs(x.p[i][0]) < EPS)
- x.p[i][0] = 0;
- }
-
- return x;
- }
-
- //矩阵显示
- void Matrix::Show() const {
- //cout << rows_num <<" "<<cols_num<< endl;//显示矩阵的行数和列数
- for (int i = 0; i < rows_num; i++) {
- for (int j = 0; j < cols_num; j++) {
- cout << p[i][j] << " ";
- }
- cout << endl;
- }
- cout << endl;
- }
- //实现行变换
- void Matrix::swapRows(int a, int b)
- {
- a--;
- b--;
- double *temp = p[a];
- p[a] = p[b];
- p[b] = temp;
- }
- //计算矩阵行列式的值
- double Matrix::det(){
- //为计算行列式做一个备份
- double ** back_up;
- back_up=new double *[rows_num];
- for(int i=0;i<rows_num;i++){
- back_up[i]=new double[cols_num];
- }
- for(int i=0;i<rows_num;i++){
- for(int j=0;j<cols_num;j++){
- back_up[i][j]=p[i][j];
- }
- }
- if(rows_num!=cols_num){
- std::abort();//只有方阵才能计算行列式,否则调用中断强制停止程序
- }
- double ans=1;
- for(int i=0;i<rows_num;i++){
- //通过行变化的形式,使得矩阵对角线上的主元素不为0
- if(abs(p[i][i])<=EPS){
- bool flag=false;
- for(int j=0;(j<cols_num)&&(!flag);j++){
- //若矩阵的一个对角线上的元素接近于0且能够通过行变换使得矩阵对角线上的元素不为0
- if((abs(p[i][j])>EPS)&&(abs(p[j][i])>EPS)){
- flag=true;
- //注:进行互换后,p[i][j]变为p[j][j],p[j][i]变为p[i][i]
- //对矩阵进行行变换
- double temp;
- for(int k=0;k<cols_num;k++){
- temp=p[i][k];
- p[i][k]=p[j][k];
- p[j][k]=temp;
- }
- }
- }
- if(flag)
- return 0;
- }
- }
- for(int i=0;i<rows_num;i++){
- for(int j=i+1;j<rows_num;j++){
- for(int k=i+1;k<cols_num;k++){
- p[j][k]-=p[i][k]*(p[j][i]*p[i][i]);
- }
- }
- }
- for(int i=0;i<rows_num;i++){
- ans*=p[i][i];
- }
- for(int i=0;i<rows_num;i++){
- for(int j=0;j<cols_num;j++){
- p[i][j]=back_up[i][j];
- }
- }
- return ans;
- }
- //返回矩阵第i行第j列的数
- double Matrix::Point(int i, int j) const{
- return this->p[i][j];
- }
- //求矩阵的逆矩阵
- Matrix Matrix::inv(Matrix A){
- if(A.rows_num!=A.cols_num){
- std::cout<<"只有方阵能求逆矩阵"<<std::endl;
- std::abort();//只有方阵能求逆矩阵
- }
- double temp;
- Matrix A_B=Matrix(A.rows_num,A.cols_num);
- A_B=A;//为矩阵A做一个备份
- Matrix B=eye(A.rows_num);
- //将小于EPS的数全部置0
- for (int i = 0; i < A.rows_num; i++) {
- for (int j = 0; j < A.cols_num; j++) {
- if (abs(A.p[i][j]) <= EPS) {
- A.p[i][j] = 0;
- }
- }
- }
- //选择需要互换的两行选主元
- for(int i=0;i<A.rows_num;i++){
- if(abs(A.p[i][i])<=EPS){
- bool flag=false;
- for(int j=0;(j<A.rows_num)&&(!flag);j++){
- if((abs(A.p[i][j])>EPS)&&(abs(A.p[j][i])>EPS)){
- flag=true;
- for(int k=0;k<A.cols_num;k++){
- temp=A.p[i][k];
- A.p[i][k]=A.p[j][k];
- A.p[j][k]=temp;
- temp=B.p[i][k];
- B.p[i][k]=B.p[j][k];
- B.p[j][k]=temp;
- }
- }
- }
- if(!flag){
- std::cout<<"逆矩阵不存在\n";
- std::abort();
- }
- }
- }
- //通过初等行变换将A变为上三角矩阵
- double temp_rate;
- for(int i=0;i<A.rows_num;i++){
- for(int j=i+1;j<A.rows_num;j++){
- temp_rate=A.p[j][i]/A.p[i][i];
- for(int k=0;k<A.cols_num;k++){
- A.p[j][k]-=A.p[i][k]*temp_rate;
- B.p[j][k]-=B.p[i][k]*temp_rate;
- }
- A.p[j][i]=0;
- }
- }
- //使对角元素均为1
- for(int i=0;i<A.rows_num;i++){
- temp=A.p[i][i];
- for(int j=0;j<A.cols_num;j++){
- A.p[i][j]/=temp;
- B.p[i][j]/=temp;
- }
- }
- //std::cout<<"算法可靠性检测,若可靠,输出上三角矩阵"<<std::endl;
- //将已经变为上三角矩阵的A,变为单位矩阵
- for(int i=A.rows_num-1;i>=1;i--){
- for(int j=i-1;j>=0;j--){
- temp=A.p[j][i];
- for(int k=0;k<A.cols_num;k++){
- A.p[j][k]-=A.p[i][k]*temp;
- B.p[j][k]-=B.p[i][k]*temp;
- }
- }
- }
- std::cout<<"算法可靠性检测,若可靠,输出单位矩阵"<<std::endl;
- for(int i=0;i<A.rows_num;i++){
- for(int j=0;j<A.cols_num;j++){
- printf("%7.4lf\t\t",A.p[i][j]);
- }
- cout << endl;
- }
- A=A_B;//还原A
- return B;//返回该矩阵的逆矩阵
- }
- //制造一个单位矩阵
- Matrix Matrix::eye(int n){
- Matrix A(n,n);
- for(int i=0;i<n;i++){
- for(int j=0;j<n;j++){
- if(i==j){
- A.p[i][j]=1;
- }else{
- A.p[i][j]=0;
- }
- }
- }
- return A;
- }
- //读取矩阵行列数
- int Matrix::row() const{
- return rows_num;
- }
- int Matrix::col() const{
- return cols_num;
- }
- //实现矩阵的转置
- Matrix Matrix::T(const Matrix & m)
- { int col_size=m.col();
- int row_size=m.row();
- Matrix mt(col_size, row_size);
- for (int i = 0; i <row_size; i++) {
- for (int j = 0; j <col_size; j++) {
- mt.p[j][i] = m.p[i][j];
- }
- }
- return mt;
- }
- //高斯消元法
- Matrix Matrix::gaussianEliminate()
- {
- Matrix Ab(*this);
- int rows = Ab.rows_num;
- int cols = Ab.cols_num;
- int Acols = cols - 1;
-
- int i = 0; //跟踪行
- int j = 0; //跟踪列
- while (i < rows)
- {
- bool flag = false;
- while (j < Acols && !flag)
- {
- if (Ab.p[i][j] != 0) {
- flag = true;
- }
- else {
- int max_row = i;
- double max_val = 0;
- for (int k = i + 1; k < rows; ++k)
- {
- double cur_abs = Ab.p[k][j] >= 0 ? Ab.p[k][j] : -1 * Ab.p[k][j];
- if (cur_abs > max_val)
- {
- max_row = k;
- max_val = cur_abs;
- }
- }
- if (max_row != i) {
- Ab.swapRows(max_row, i);
- flag = true;
- }
- else {
- j++;
- }
- }
- }
- if (flag)
- {
- for (int t = i + 1; t < rows; t++) {
- for (int s = j + 1; s < cols; s++) {
- Ab.p[t][s] = Ab.p[t][s] - Ab.p[i][s] * (Ab.p[t][j] / Ab.p[i][j]);
- if (abs(Ab.p[t][s]) <EPS)
- Ab.p[t][s] = 0;
- }
- Ab.p[t][j] = 0;
- }
- }
- i++;
- j++;
- }
- return Ab;
- }
- //实现矩阵的输入
- istream& operator>>(istream& is, Matrix& m)
- {
- for (int i = 0; i < m.rows_num; i++) {
- for (int j = 0; j < m.cols_num; j++) {
- is >> m.p[i][j];
- }
- }
- return is;
- }
-

主程序
-
-
- #include "matrix.h"
- using namespace std;
-
- int main()
- {
- Matrix A = Matrix(3, 3);
- cin >> A;
- Matrix b = Matrix(3, 1);
- cin >> b;
- Matrix x = Matrix::Solve(A, b);
- x.Show();
- return 0;
- }
-

求赞,求转发
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。