实现了两个向量和矩阵的基本类,针对处理对象创建了MatrixVector类和MatrixMatrix类。使用gauss法同时实现了线性方程组的求解和矩阵的求逆
0. 预处理
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
using namespace std;
//
double DoubleRnd(){
return rand() / 32767.0; // RAND_MAX = (int)32767 , 此处表示0-1的随机小数
}
//
1. Vector向量类
class Vector{
private:
int nDim;
double* Vect;
public:
Vector(int nDim);
Vector(Vector& v);
~Vector() { delete[] Vect;}
void Set(int nX, double r) { Vect[MakeIndex(nX)] = r;}
double Get(int nX) { return Vect[MakeIndex(nX)]; }
int GetDim() {return nDim;}
private:
void InitMemory() { Vect = new double[nDim];}
int MakeIndex(int nX) { return nX - 1; }
void Set0(int nX) { Set(nX, 0); }
public:
void InitNul();
void InitRnd();
friend ostream& operator<<(ostream& os, Vector& v);
///高斯求解所需函数
void Divid(double R, int nVerh);
void Minus(double R, int nNizz, int nVerh);
};
Vector::Vector(int nDim){
this->nDim = nDim;
InitMemory();
}
Vector::Vector(Vector& v){
nDim = v.nDim;
InitMemory();
for(int i = 1; i <= nDim; i++)
Set(i, v.Get(i));
}
void Vector::InitNul(){
for(int i =1; i <= nDim; i++) Set0(i);
}
void Vector::InitRnd(){
for(int i =1; i <= nDim; i++) Set(i, DoubleRnd());
}
void Vector::Divid(double R, int nVerh){
Set(nVerh, Get(nVerh) / R);
}
void Vector::Minus(double R, int nNizz, int nVerh){
Set(nNizz, Get(nNizz)-R*Get(nVerh));
}
ostream& operator<<(ostream& os, Vector& v){
for(int j = 1; j <= v.nDim; j++){
os.width(10);
os.precision(3);
os << v.Get(j) << " ";
}
return os;
}
2. Matrix矩阵类
class Matrix{
private:
int nDim;
double* Matr;
public:
Matrix(int nDim);
Matrix(Matrix& m);
~Matrix(){delete[] Matr;}
void Set(int nX, int nY, double r) {Matr[MakeIndex(nX, nY)] = r;}
double Get(int nX, int nY) {return Matr[MakeIndex(nX, nY)]; }
int GetDim(){return nDim;}
private:
void InitMemory(){ Matr = new double[nDim * nDim]; }
int MakeIndex(int nX, int nY){return (nX - 1) * nDim + (nY - 1);}
void Set0(int nX, int nY) { Set(nX,nY,0);}
void Set1(int nX, int nY) { Set(nX,nY,1);}
public:
void InitNul();
void InitOne();
void InitRnd();
friend ostream& operator<<(ostream& os, Matrix& m);
void Divid(double R, int nVerh); // 将每一行除以其对应的对角线元素
void Minus(double R, int nNizz, int nVerh);
};
implementation
Matrix::Matrix(int nDim){
this->nDim = nDim;
InitMemory();
}
Matrix::Matrix(Matrix& m){
nDim = m.nDim;
InitMemory();
for(int i = 1; i<=nDim; i++)
for(int j = 1; j<=nDim; j++)
Set(i, j, m.Get(i, j));
}
void Matrix::InitNul(){
for(int i = 1; i <= nDim; i++)
for(int j = 1; j <= nDim; j++)
Set0(i, j);
}
void Matrix::InitOne(){
for(int i = 1; i <= nDim; i++)
for(int j = 1; j <= nDim; j++){
Set0(i, j);
if(i != j) continue;
Set1(i, j);
}
}
void Matrix::InitRnd(){
for(int i = 1; i <= nDim; i++)
for(int j = 1; j <= nDim; j++)
Set(i, j, DoubleRnd());
}
ostream& operator<<(ostream& os, Matrix& m){
os << m.nDim << endl;
for(int i = 1; i <= m.nDim; i++){
for(int j = 1; j <= m.nDim; j++){
os.width(10);
os.precision(3);
os << m.Get(i, j) << " ";
}
os << endl;
}
return os;
}
void Matrix::Divid(double R, int nVerh){
for (int j = 1; j <= nDim; j++)
Set(nVerh, j, Get(nVerh, j)/R);
}
void Matrix::Minus(double R, int nNizz, int nVerh){
for (int j = 1; j <= nDim; j++)
Set(nNizz, j, Get(nNizz, j)-R*Get(nVerh, j));
}
3. MatrixVector类
class MatrixVector{ //系数矩阵Matrix + 常数向量 Vector = MatrixVector类:用于求解线性方程组
private:
int nDim;
Matrix MMM;
Vector VVV;
public:
MatrixVector(int nDim);
void InitRnd();
void InitMatrix(Matrix& M);
void InitVector(Vector& V);
Vector& GetVector(){ return VVV; }
friend ostream& operator<<(ostream& os, MatrixVector& mv);
//以下为高斯求解所需的函数
void Divid(double R, int nVerh){ MMM.Divid(R, nVerh); VVV.Divid(R, nVerh);} // 除法,矩阵除以向量VVV
void Minus(double R, int nNizz, int nVerh) {MMM.Minus(R, nNizz, nVerh); VVV.Minus(R, nNizz, nVerh);} // 减法,矩阵减去向量VVV
void Tuda();
void Obratno();
};
implementation
MatrixVector::MatrixVector(int nDim) : MMM(nDim), VVV(nDim){ //初始化列表:等同于Matrix MMM(int nDim);Vector VVV(int nDim);
this->nDim = nDim;
}
void MatrixVector::InitRnd(){
MMM.InitRnd();
VVV.InitRnd();
}
void MatrixVector::InitMatrix(Matrix& M){
for(int i = 1; i <= nDim; i++)
for(int j = 1; j <= nDim; j++)
M.Set(i, j, MMM.Get(i, j));
}
void MatrixVector::InitVector(Vector& V){
for(int i = 1; i <= nDim; i++)
V.Set(i, VVV.Get(i));
}
ostream& operator<<(ostream& os, MatrixVector& mv){
os << mv.nDim << endl;
for(int i = 1; i <= mv.nDim; i++){
for(int j = 1 ; j <= mv.nDim; j++){
os.width(10);
os.precision(3);
os << mv.MMM.Get(i, j) << " ";
}
os.width(14);
os.precision(3);
os << mv.VVV.Get(i) << " ";
os << endl;
}
return os;
}
void MatrixVector::Tuda(){ // 直接高斯
for(int i = 1; i <= nDim; i++){
Divid(MMM.Get(i, i), i);
for(int j =i + 1; j <= nDim; j++)
Minus(MMM.Get(j, i), j, i);
}
}
void MatrixVector::Obratno(){ // 相反方向(从右到左从下至上)再化简一次矩阵(由上三角转为单位矩阵) O(n^3) Matrix::Minus中还有一重for循环,可以修改为O(n^2) 但是影响代码耦合度
for(int i = nDim; i >= 2; i--)
for(int j = i - 1; j >= 1; j--)
Minus(MMM.Get(j, i), j, i);
}
///
void Multi(Matrix& MMM, Vector& VVV, Vector& VVVotv){
int nDim = MMM.GetDim();
for(int i = 1; i <= nDim; i++){
double R = 0;
for(int j = 1; j <= nDim; j++)
R += MMM.Get(i, j) * VVV.Get(j);
VVVotv.Set(i, R);
}
}
double Nevya(Vector& VVV1, Vector& VVV2){
int nDim = VVV1.GetDim();
double R = 0;
for(int i = 1; i <= nDim; i++) R += pow(VVV1.Get(i) - VVV2.Get(i), 2);
return pow(R, 0.5);
}
4. MatrixMatrix类
class MatrixMatrix{ //系数矩阵Matrix + 单位矩阵Matrix = MatrixMatrix类:用于求逆矩阵
private:
int nDim;
Matrix MMM;
Matrix VVV;
public:
MatrixMatrix(int nDim);
void InitRnd();
void InitMatrix(Matrix& M);
Matrix& GetMatrix() {return VVV;}
friend ostream& operator<<(ostream& os, MatrixMatrix& mv);
//以下为高斯求逆矩阵所需的函数
void Divid(double R, int nVerh){ MMM.Divid(R, nVerh); VVV.Divid(R, nVerh);}
void Minus(double R, int nNizz, int nVerh) {MMM.Minus(R, nNizz, nVerh); VVV.Minus(R, nNizz, nVerh);}
void Tuda();
void Obratno();
};
implementation
MatrixMatrix::MatrixMatrix(int nDim) : MMM(nDim), VVV(nDim){ //初始化列表:等同于Matrix MMM(int nDim); Matrix VVV(int nDim);
this->nDim = nDim;
}
void MatrixMatrix::InitRnd(){
MMM.InitRnd();
VVV.InitOne(); // 注意这里初始化为单位矩阵
}
void MatrixMatrix::InitMatrix(Matrix& M){
for(int i = 1; i <= nDim; i++)
for(int j = 1; j <= nDim; j++)
M.Set(i, j, MMM.Get(i, j));
}
ostream& operator<<(ostream& os, MatrixMatrix& mv){
os << mv.nDim << endl;
for(int i = 1; i <= mv.nDim; i++){
for(int j = 1 ; j <= mv.nDim; j++){
os.width(10);
os.precision(3);
os << mv.MMM.Get(i, j) << " ";
}
os << " ";
for(int j = 1; j <= mv.nDim; j++){
os.width(10);
os.precision(3);
os << mv.VVV.Get(i, j) << " ";
}
os << endl;
}
return os;
}
void MatrixMatrix::Tuda(){
for(int i = 1; i <= nDim; i++){
Divid(MMM.Get(i, i), i);
for(int j =i + 1; j <= nDim; j++)
Minus(MMM.Get(j, i), j, i);
}
}
void MatrixMatrix::Obratno(){ // O(n^3) - Matrix::Minus中还有一重for循环 ,不能改为O(n^2)
for(int i = nDim; i >= 2; i--)
for(int j = i - 1; j >= 1; j--)
Minus(MMM.Get(j, i), j, i);
}
///
void Multi(Matrix& MMM, Matrix& VVV, Matrix& VVVotv){ // 矩阵乘法
int nDim = MMM.GetDim();
for(int i = 1; i <= nDim; i++)
for(int j = 1; j <= nDim; j++){
double R = 0;
for(int k = 1; k <= nDim; k++)
R += MMM.Get(i, k) * VVV.Get(k, j);
VVVotv.Set(i, j, R);
}
}
double Nevya(Matrix& VVV1, Matrix& VVV2){ // 误差
int nDim = VVV1.GetDim();
double R = 0;
for(int i = 1; i <= nDim; i++) for(int j = 1; j <= nDim; j++)R += pow(VVV1.Get(i, j) - VVV2.Get(i, j), 2);
return pow(R, 0.5);
}
5. 运行调用
int main(int argc, char** argv){
srand(time(NULL)); // 表示设置一个随机种子,每次运行都能保证随机种子不同。(因为rand会默认取上一次随机出来的结果,达不到每次调用都随机的效果)
int nDim = 4;
//
MatrixVector MV(nDim); MV.InitRnd(); cout << MV << endl;
Matrix M(nDim); MV.InitMatrix(M);
Vector V(nDim); MV.InitVector(V);
MV.Tuda(); MV.Obratno(); cout << MV << endl;
Vector VV(nDim);
Multi(M, MV.GetVector(), VV); cout << VV<< endl << endl;
cout << Nevya(VV, V) << endl;
//
cout << endl << endl<< endl<< endl<< endl<< endl<< endl<< endl;
//
MatrixMatrix MM(nDim); MM.InitRnd(); cout << MM << endl;
MM.InitMatrix(M);
Matrix VM(nDim);
MM.Tuda(); MM.Obratno(); cout << MM << endl;
Matrix VVM(nDim);
Multi(M, MM.GetMatrix() , VVM); cout << VVM << endl;
cout << Nevya(VVM, VM) << endl;
//
return 0;
}