当前位置:   article > 正文

C++实现矩阵类(附代码和功能)_c++矩阵

c++矩阵

       阅读这篇文章需要掌握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

  1. #ifndef PCH_H
  2. #define PCH_H
  3. #include <cmath>
  4. #include <iostream>
  5. #include <stdlib.h>
  6. #include <cmath>
  7. // TODO: 添加要在此处预编译的标头
  8. #endif //PCH_H

 头文件.h

  1. /*
  2. author: cclplus
  3. date:2018/12/09
  4. if you think it is necessary to reward me,
  5. my alipay account number is 707101557@qq.com
  6. */
  7. #ifndef __MATRIX_CLL_H__
  8. #define __MATRIX_CCL_H__
  9. #include "pch.h"
  10. class Matrix {
  11. private:
  12. int rows_num, cols_num;
  13. double **p;
  14. void initialize();//初始化矩阵
  15. public:
  16. Matrix(int, int);
  17. Matrix(int, int, double);//预配分空间
  18. virtual ~Matrix();//析构函数应当是虚函数,除非此类不用做基类
  19. Matrix& operator=(const Matrix&);//矩阵的复制
  20. Matrix& operator=(double *);//将数组的值传给矩阵
  21. Matrix& operator+=(const Matrix&);//矩阵的+=操作
  22. Matrix& operator-=(const Matrix&);//-=
  23. Matrix& operator*=(const Matrix&);//*=
  24. Matrix operator*(const Matrix & m)const;
  25. static Matrix Solve(const Matrix&, const Matrix&);//求解线性方程组Ax=b
  26. void Show() const;//矩阵显示
  27. void swapRows(int, int);
  28. double det();//求矩阵的行列式
  29. double Point(int i, int j) const;
  30. static Matrix inv(Matrix);//求矩阵的逆矩阵
  31. static Matrix eye(int );//制造一个单位矩阵
  32. int row() const;
  33. int col() const;
  34. static Matrix T(const Matrix & m);//矩阵转置的实现,且不改变矩阵
  35. Matrix gaussianEliminate();//高斯消元法
  36. friend std::istream& operator>>(std::istream&, Matrix&);//实现矩阵的输入
  37. };
  38. #endif

头文件.cpp

  1. /*
  2. author: cclplus
  3. date : 2018 / 12 / 09
  4. if you think it is necessary to reward me,
  5. my alipay account number is 707101557@qq.com
  6. */
  7. #include "pch.h"
  8. #include "matrix.h"
  9. using std::endl;
  10. using std::cout;
  11. using std::istream;
  12. const double EPS = 1e-10;
  13. void Matrix::initialize() {//初始化矩阵大小
  14. p = new double*[rows_num];//分配rows_num个指针
  15. for (int i = 0; i < rows_num; ++i) {
  16. p[i] = new double[cols_num];//为p[i]进行动态内存分配,大小为cols
  17. }
  18. }
  19. //声明一个全0矩阵
  20. Matrix::Matrix(int rows, int cols)
  21. {
  22. rows_num = rows;
  23. cols_num = cols;
  24. initialize();
  25. for (int i = 0; i < rows_num; i++) {
  26. for (int j = 0; j < cols_num; j++) {
  27. p[i][j] = 0;
  28. }
  29. }
  30. }
  31. //声明一个值全部为value的矩阵
  32. Matrix::Matrix(int rows, int cols, double value)
  33. {
  34. rows_num = rows;
  35. cols_num = cols;
  36. initialize();
  37. for (int i = 0; i < rows_num; i++) {
  38. for (int j = 0; j < cols_num; j++) {
  39. p[i][j] = value;
  40. }
  41. }
  42. }
  43. //析构函数
  44. Matrix::~Matrix() {
  45. for (int i = 0; i < rows_num; ++i) {
  46. delete[] p[i];
  47. }
  48. delete[] p;
  49. }
  50. //实现矩阵的复制
  51. Matrix& Matrix::operator=(const Matrix& m)
  52. {
  53. if (this == &m) {
  54. return *this;
  55. }
  56. if (rows_num != m.rows_num || cols_num != m.cols_num) {
  57. for (int i = 0; i < rows_num; ++i) {
  58. delete[] p[i];
  59. }
  60. delete[] p;
  61. rows_num = m.rows_num;
  62. cols_num = m.cols_num;
  63. initialize();
  64. }
  65. for (int i = 0; i < rows_num; i++) {
  66. for (int j = 0; j < cols_num; j++) {
  67. p[i][j] = m.p[i][j];
  68. }
  69. }
  70. return *this;
  71. }
  72. //将数组的值传递给矩阵(要求矩阵的大小已经被声明过了)
  73. Matrix& Matrix::operator=(double *a){
  74. for(int i=0;i<rows_num;i++){
  75. for(int j=0;j<cols_num;j++){
  76. p[i][j]= *(a+i*cols_num+j);
  77. }
  78. }
  79. return *this;
  80. }
  81. //+=操作
  82. Matrix& Matrix::operator+=(const Matrix& m)
  83. {
  84. for (int i = 0; i < rows_num; i++) {
  85. for (int j = 0; j < cols_num; j++) {
  86. p[i][j] += m.p[i][j];
  87. }
  88. }
  89. return *this;
  90. }
  91. //实现-=
  92. Matrix& Matrix::operator-=(const Matrix& m)
  93. {
  94. for (int i = 0; i < rows_num; i++) {
  95. for (int j = 0; j < cols_num; j++) {
  96. p[i][j] -= m.p[i][j];
  97. }
  98. }
  99. return *this;
  100. }
  101. //实现*=
  102. Matrix& Matrix::operator*=(const Matrix& m)
  103. {
  104. Matrix temp(rows_num, m.cols_num);//若C=AB,则矩阵C的行数等于矩阵A的行数,C的列数等于B的列数。
  105. for (int i = 0; i < temp.rows_num; i++) {
  106. for (int j = 0; j < temp.cols_num; j++) {
  107. for (int k = 0; k < cols_num; k++) {
  108. temp.p[i][j] += (p[i][k] * m.p[k][j]);
  109. }
  110. }
  111. }
  112. *this = temp;
  113. return *this;
  114. }
  115. //实现矩阵的乘法
  116. Matrix Matrix::operator*(const Matrix & m)const{
  117. Matrix ba_M(rows_num,m.cols_num,0.0);
  118. for(int i=0;i<rows_num;i++){
  119. for(int j=0;j<m.cols_num;j++){
  120. for(int k=0;k<cols_num;k++){
  121. ba_M.p[i][j]+=(p[i][k]*m.p[k][j]);
  122. }
  123. }
  124. }
  125. return ba_M;
  126. }
  127. //解方程Ax=b
  128. Matrix Matrix::Solve(const Matrix &A, const Matrix &b)
  129. {
  130. //高斯消去法实现Ax=b的方程求解
  131. for (int i = 0; i < A.rows_num; i++) {
  132. if (A.p[i][i] == 0) {
  133. cout << "请重新输入" << endl;
  134. }
  135. for (int j = i + 1; j < A.rows_num; j++) {
  136. for (int k = i + 1; k < A.cols_num; k++) {
  137. A.p[j][k] -= A.p[i][k] * (A.p[j][i] / A.p[i][i]);
  138. if (abs(A.p[j][k]) < EPS)
  139. A.p[j][k] = 0;
  140. }
  141. b.p[j][0] -= b.p[i][0] * (A.p[j][i] / A.p[i][i]);
  142. if (abs(A.p[j][0]) < EPS)
  143. A.p[j][0] = 0;
  144. A.p[j][i] = 0;
  145. }
  146. }
  147. // 反向代换
  148. Matrix x(b.rows_num, 1);
  149. x.p[x.rows_num - 1][0] = b.p[x.rows_num - 1][0] / A.p[x.rows_num - 1][x.rows_num - 1];
  150. if (abs(x.p[x.rows_num - 1][0]) < EPS)
  151. x.p[x.rows_num - 1][0] = 0;
  152. for (int i = x.rows_num - 2; i >= 0; i--) {
  153. double sum = 0;
  154. for (int j = i + 1; j < x.rows_num; j++) {
  155. sum += A.p[i][j] * x.p[j][0];
  156. }
  157. x.p[i][0] = (b.p[i][0] - sum) / A.p[i][i];
  158. if (abs(x.p[i][0]) < EPS)
  159. x.p[i][0] = 0;
  160. }
  161. return x;
  162. }
  163. //矩阵显示
  164. void Matrix::Show() const {
  165. //cout << rows_num <<" "<<cols_num<< endl;//显示矩阵的行数和列数
  166. for (int i = 0; i < rows_num; i++) {
  167. for (int j = 0; j < cols_num; j++) {
  168. cout << p[i][j] << " ";
  169. }
  170. cout << endl;
  171. }
  172. cout << endl;
  173. }
  174. //实现行变换
  175. void Matrix::swapRows(int a, int b)
  176. {
  177. a--;
  178. b--;
  179. double *temp = p[a];
  180. p[a] = p[b];
  181. p[b] = temp;
  182. }
  183. //计算矩阵行列式的值
  184. double Matrix::det(){
  185. //为计算行列式做一个备份
  186. double ** back_up;
  187. back_up=new double *[rows_num];
  188. for(int i=0;i<rows_num;i++){
  189. back_up[i]=new double[cols_num];
  190. }
  191. for(int i=0;i<rows_num;i++){
  192. for(int j=0;j<cols_num;j++){
  193. back_up[i][j]=p[i][j];
  194. }
  195. }
  196. if(rows_num!=cols_num){
  197. std::abort();//只有方阵才能计算行列式,否则调用中断强制停止程序
  198. }
  199. double ans=1;
  200. for(int i=0;i<rows_num;i++){
  201. //通过行变化的形式,使得矩阵对角线上的主元素不为0
  202. if(abs(p[i][i])<=EPS){
  203. bool flag=false;
  204. for(int j=0;(j<cols_num)&&(!flag);j++){
  205. //若矩阵的一个对角线上的元素接近于0且能够通过行变换使得矩阵对角线上的元素不为0
  206. if((abs(p[i][j])>EPS)&&(abs(p[j][i])>EPS)){
  207. flag=true;
  208. //注:进行互换后,p[i][j]变为p[j][j],p[j][i]变为p[i][i]
  209. //对矩阵进行行变换
  210. double temp;
  211. for(int k=0;k<cols_num;k++){
  212. temp=p[i][k];
  213. p[i][k]=p[j][k];
  214. p[j][k]=temp;
  215. }
  216. }
  217. }
  218. if(flag)
  219. return 0;
  220. }
  221. }
  222. for(int i=0;i<rows_num;i++){
  223. for(int j=i+1;j<rows_num;j++){
  224. for(int k=i+1;k<cols_num;k++){
  225. p[j][k]-=p[i][k]*(p[j][i]*p[i][i]);
  226. }
  227. }
  228. }
  229. for(int i=0;i<rows_num;i++){
  230. ans*=p[i][i];
  231. }
  232. for(int i=0;i<rows_num;i++){
  233. for(int j=0;j<cols_num;j++){
  234. p[i][j]=back_up[i][j];
  235. }
  236. }
  237. return ans;
  238. }
  239. //返回矩阵第i行第j列的数
  240. double Matrix::Point(int i, int j) const{
  241. return this->p[i][j];
  242. }
  243. //求矩阵的逆矩阵
  244. Matrix Matrix::inv(Matrix A){
  245. if(A.rows_num!=A.cols_num){
  246. std::cout<<"只有方阵能求逆矩阵"<<std::endl;
  247. std::abort();//只有方阵能求逆矩阵
  248. }
  249. double temp;
  250. Matrix A_B=Matrix(A.rows_num,A.cols_num);
  251. A_B=A;//为矩阵A做一个备份
  252. Matrix B=eye(A.rows_num);
  253. //将小于EPS的数全部置0
  254. for (int i = 0; i < A.rows_num; i++) {
  255. for (int j = 0; j < A.cols_num; j++) {
  256. if (abs(A.p[i][j]) <= EPS) {
  257. A.p[i][j] = 0;
  258. }
  259. }
  260. }
  261. //选择需要互换的两行选主元
  262. for(int i=0;i<A.rows_num;i++){
  263. if(abs(A.p[i][i])<=EPS){
  264. bool flag=false;
  265. for(int j=0;(j<A.rows_num)&&(!flag);j++){
  266. if((abs(A.p[i][j])>EPS)&&(abs(A.p[j][i])>EPS)){
  267. flag=true;
  268. for(int k=0;k<A.cols_num;k++){
  269. temp=A.p[i][k];
  270. A.p[i][k]=A.p[j][k];
  271. A.p[j][k]=temp;
  272. temp=B.p[i][k];
  273. B.p[i][k]=B.p[j][k];
  274. B.p[j][k]=temp;
  275. }
  276. }
  277. }
  278. if(!flag){
  279. std::cout<<"逆矩阵不存在\n";
  280. std::abort();
  281. }
  282. }
  283. }
  284. //通过初等行变换将A变为上三角矩阵
  285. double temp_rate;
  286. for(int i=0;i<A.rows_num;i++){
  287. for(int j=i+1;j<A.rows_num;j++){
  288. temp_rate=A.p[j][i]/A.p[i][i];
  289. for(int k=0;k<A.cols_num;k++){
  290. A.p[j][k]-=A.p[i][k]*temp_rate;
  291. B.p[j][k]-=B.p[i][k]*temp_rate;
  292. }
  293. A.p[j][i]=0;
  294. }
  295. }
  296. //使对角元素均为1
  297. for(int i=0;i<A.rows_num;i++){
  298. temp=A.p[i][i];
  299. for(int j=0;j<A.cols_num;j++){
  300. A.p[i][j]/=temp;
  301. B.p[i][j]/=temp;
  302. }
  303. }
  304. //std::cout<<"算法可靠性检测,若可靠,输出上三角矩阵"<<std::endl;
  305. //将已经变为上三角矩阵的A,变为单位矩阵
  306. for(int i=A.rows_num-1;i>=1;i--){
  307. for(int j=i-1;j>=0;j--){
  308. temp=A.p[j][i];
  309. for(int k=0;k<A.cols_num;k++){
  310. A.p[j][k]-=A.p[i][k]*temp;
  311. B.p[j][k]-=B.p[i][k]*temp;
  312. }
  313. }
  314. }
  315. std::cout<<"算法可靠性检测,若可靠,输出单位矩阵"<<std::endl;
  316. for(int i=0;i<A.rows_num;i++){
  317. for(int j=0;j<A.cols_num;j++){
  318. printf("%7.4lf\t\t",A.p[i][j]);
  319. }
  320. cout << endl;
  321. }
  322. A=A_B;//还原A
  323. return B;//返回该矩阵的逆矩阵
  324. }
  325. //制造一个单位矩阵
  326. Matrix Matrix::eye(int n){
  327. Matrix A(n,n);
  328. for(int i=0;i<n;i++){
  329. for(int j=0;j<n;j++){
  330. if(i==j){
  331. A.p[i][j]=1;
  332. }else{
  333. A.p[i][j]=0;
  334. }
  335. }
  336. }
  337. return A;
  338. }
  339. //读取矩阵行列数
  340. int Matrix::row() const{
  341. return rows_num;
  342. }
  343. int Matrix::col() const{
  344. return cols_num;
  345. }
  346. //实现矩阵的转置
  347. Matrix Matrix::T(const Matrix & m)
  348. { int col_size=m.col();
  349. int row_size=m.row();
  350. Matrix mt(col_size, row_size);
  351. for (int i = 0; i <row_size; i++) {
  352. for (int j = 0; j <col_size; j++) {
  353. mt.p[j][i] = m.p[i][j];
  354. }
  355. }
  356. return mt;
  357. }
  358. //高斯消元法
  359. Matrix Matrix::gaussianEliminate()
  360. {
  361. Matrix Ab(*this);
  362. int rows = Ab.rows_num;
  363. int cols = Ab.cols_num;
  364. int Acols = cols - 1;
  365. int i = 0; //跟踪行
  366. int j = 0; //跟踪列
  367. while (i < rows)
  368. {
  369. bool flag = false;
  370. while (j < Acols && !flag)
  371. {
  372. if (Ab.p[i][j] != 0) {
  373. flag = true;
  374. }
  375. else {
  376. int max_row = i;
  377. double max_val = 0;
  378. for (int k = i + 1; k < rows; ++k)
  379. {
  380. double cur_abs = Ab.p[k][j] >= 0 ? Ab.p[k][j] : -1 * Ab.p[k][j];
  381. if (cur_abs > max_val)
  382. {
  383. max_row = k;
  384. max_val = cur_abs;
  385. }
  386. }
  387. if (max_row != i) {
  388. Ab.swapRows(max_row, i);
  389. flag = true;
  390. }
  391. else {
  392. j++;
  393. }
  394. }
  395. }
  396. if (flag)
  397. {
  398. for (int t = i + 1; t < rows; t++) {
  399. for (int s = j + 1; s < cols; s++) {
  400. Ab.p[t][s] = Ab.p[t][s] - Ab.p[i][s] * (Ab.p[t][j] / Ab.p[i][j]);
  401. if (abs(Ab.p[t][s]) <EPS)
  402. Ab.p[t][s] = 0;
  403. }
  404. Ab.p[t][j] = 0;
  405. }
  406. }
  407. i++;
  408. j++;
  409. }
  410. return Ab;
  411. }
  412. //实现矩阵的输入
  413. istream& operator>>(istream& is, Matrix& m)
  414. {
  415. for (int i = 0; i < m.rows_num; i++) {
  416. for (int j = 0; j < m.cols_num; j++) {
  417. is >> m.p[i][j];
  418. }
  419. }
  420. return is;
  421. }

主程序

  1. #include "matrix.h"
  2. using namespace std;
  3. int main()
  4. {
  5. Matrix A = Matrix(3, 3);
  6. cin >> A;
  7. Matrix b = Matrix(3, 1);
  8. cin >> b;
  9. Matrix x = Matrix::Solve(A, b);
  10. x.Show();
  11. return 0;
  12. }

求赞,求转发

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/732348
推荐阅读
相关标签
  

闽ICP备14008679号