c++矩阵运算
优化了一些算法
#pragma once #include <iostream> #include <iomanip> #include <string> #define OVERFLOWED 1E-12 class Matrix { public: Matrix(int m, int n); //构建一个m*n的全零矩阵 Matrix(int n); //构建一个n*n的单位矩阵 Matrix(const Matrix &); //拷贝构造函数,深拷贝 Matrix(double* items, int m, int n);//根据数组拷贝一个矩阵 ~Matrix(); static Matrix FromFile(std::string file); int getRowNum() const; //返回矩阵的行数 int getColNum() const; //返回矩阵的列数 Matrix Trans() const; //将矩阵转置 double get(int i, int j) const; //返回矩阵第i行j列元素 void set(int i, int j, double val); //设置矩阵第i行j列元素 Matrix operator +(const Matrix &m); //两个矩阵相加 Matrix operator -(const Matrix &m); //两个矩阵相减 Matrix operator *(const Matrix &m); //两个矩阵相乘 Matrix operator *(const double f); //矩阵乘以常数 Matrix& operator=(const Matrix& m); Matrix Inverse(); friend std::ostream& operator <<(std::ostream &os, const Matrix &m); private: double *item; //指向矩阵首元素 int rowNum; //矩阵行数 int colNum; //矩阵列数 private: //矩阵初等行变换 //如果j=-1,则对i扩大multiply倍 //如果j在取值范围内,则将第i行扩大multiply倍加到j行 void RowSwap(int i, int j, double multiply); //交换两行 void RowSwap(int i, int j); void FlowOver(); };
#include "Matrix.h" #include <vector> #include <cmath> #include <fstream> #include <sstream> using namespace std; Matrix::Matrix(int m, int n) { if (m < 0 || n < 0) { cout << "矩阵大小不能为负\n"; return; } rowNum = m; colNum = n; item = new double[m*n]; for (int i = 0; i < m*n; i++) { item[i] = 0; } } //也可用二维数组初始化 Matrix::Matrix(double* items, int m, int n) { rowNum = m; colNum = n; item = new double[m*n]; for (int i = 0; i < colNum*rowNum; i++) { item[i] = items[i]; } } Matrix::Matrix(int n) { rowNum = colNum = n; item = new double[n*n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i == j) set(i, j, 1.0); else set(i, j, 0); } } } Matrix::Matrix(const Matrix &M) { colNum = M.colNum; rowNum = M.rowNum; //这里不能对指针直接赋值,复制对求逆、转置等操作会影响原矩阵 item = new double[colNum*rowNum]; for (int i = 0; i < colNum*rowNum; i++) { item[i] = M.item[i]; } } Matrix& Matrix::operator=(const Matrix & M) { colNum = M.colNum; rowNum = M.rowNum; if (item != nullptr) delete[] item; item = new double[colNum*rowNum]; for (int i = 0; i < colNum*rowNum; i++) { item[i] = M.item[i]; } return *this; } Matrix Matrix::FromFile(std::string file) { ifstream read(file); if (!read.is_open()) { cout << "Matrix::未能打开文件\n"; } int rows = 0; string line; vector<double> nums; while (getline(read, line)) { istringstream record(line); double num = 0.0; while (record >> num) nums.push_back(num); rows++; } return Matrix(&(*nums.begin()), rows, nums.size() / rows); } Matrix::~Matrix() { delete[] item; } double Matrix::get(int i, int j) const { return item[i*colNum + j]; } void Matrix::set(int i, int j, double value) { item[i*colNum + j] = value; } void Matrix::RowSwap(int i, int j, double multiply) { if (j == -1) { for (int k = 0; k < colNum; k++) { set(i, k, multiply*get(i, k)); } } else { for (int k = 0; k < colNum; k++) { set(j, k, multiply*get(i, k) + get(j, k)); } } } void Matrix::RowSwap(int i, int j) { Matrix _copy = *this; for (int k = 0; k < colNum; k++) { double swap = _copy.get(j, k); set(j, k, _copy.get(i, k)); set(i, k, swap); } } Matrix Matrix::Trans() const { Matrix _copy = *this; _copy.rowNum = this->colNum; _copy.colNum = this->rowNum; for (int i = 0; i < _copy.rowNum; i++) { for (int j = 0; j < _copy.colNum; j++) { _copy.set(i, j, get(j, i)); } } return _copy; } int Matrix::getRowNum() const { return rowNum; } int Matrix::getColNum() const { return colNum; } ostream& operator <<(ostream &os, const Matrix &m) { for (int i = 0; i < m.rowNum; i++) { for (int j = 0; j < m.colNum; j++) os << std::setw(10) << std::fixed << std::setprecision(12) << m.get(i, j) << " "; os << "\n"; } os.flush(); return os; } Matrix Matrix::operator +(const Matrix &m) { if (m.colNum != colNum || m.rowNum != rowNum) return *this; Matrix _copy = *this; for (int i = 0; i < rowNum; i++) { for (int j = 0; j < colNum; j++) { _copy.set(i, j, get(i, j) + m.get(i, j)); } } return _copy; } Matrix Matrix::operator -(const Matrix &m) { if (m.colNum != colNum || m.rowNum != rowNum) return *this; Matrix _copy = *this; for (int i = 0; i < rowNum; i++) { for (int j = 0; j < colNum; j++) { _copy.set(i, j, get(i, j) - m.get(i, j)); } } return _copy; } Matrix Matrix::operator *(const double f) { Matrix _copy = *this; for (int i = 0; i < rowNum; i++) { for (int j = 0; j < colNum; j++) { _copy.set(i, j, get(i, j)*f); } } return _copy; } Matrix Matrix::operator *(const Matrix &m) { if (colNum != m.rowNum) { cout << "无法相乘!"; return *this; } Matrix _copy(rowNum, m.getColNum()); for (int i = 0; i < rowNum; i++) { for (int j = 0; j < m.colNum; j++) { double sum = 0; for (int k = 0; k < m.rowNum; k++) { sum += get(i, k)*m.get(k, j); } _copy.set(i, j, sum); } } return _copy; } Matrix Matrix::Inverse() { Matrix _copy = *this; //变换结果 Matrix result(colNum); if (colNum != rowNum) { cout << "矩阵不可逆!" << endl; return *this; } for (int i = 0; i < rowNum; i++) { int MaxRow = i; //首先找到第i列的绝对值最大的数,并将该行和第i行互换 double max = abs(_copy.get(i, i)); for (int j = i; j < colNum; j++) { if (abs(_copy.get(j, i))>max) { max = abs(_copy.get(j, i)); MaxRow = j; } } //交换j,i两行 if (MaxRow != i) { result.RowSwap(i, MaxRow); _copy.RowSwap(i, MaxRow); } //将第i行做初等行变换,将第一个非0元素化为1 double r = 1.0 / _copy.get(i, i); _copy.RowSwap(i, -1, r); result.RowSwap(i, -1, r); //消元 for (int j = 0; j < rowNum; j++) { if (j == i) continue; r = -_copy.get(j, i); _copy.RowSwap(i, j, r); result.RowSwap(i, j, r); } } //result.FlowOver(); return result; } void Matrix::FlowOver() { for (int i = 0; i < rowNum;i++) { for (int j = 0; j < colNum;j++) { if (abs(get(i, j)) <= OVERFLOWED) set(i, j, 0); } } }