矩阵运算系统
需求分析
- 编写一个矩阵运算系统,能够实现对矩阵的常规运算,基本要求包括:
(1) 一维矩阵类,能预定义矩阵的长度或运行中动态定义矩阵的长度。通过运算符重载,该类需能实现一维矩阵的基本算术运算(加、减、乘、除等);
(2) 二维矩阵类,该类可通过继承一维矩阵类修改获得,也可重新定义。二维矩阵类需能够自由定义矩阵的维度,并同时能实现二维矩阵的基本算术运算;
(3) 两个类都必须同时包含打印函数,能清楚打印出当前矩阵的内容;
(4) 两个类都必须含有重载的复制构造函数和复制成员函数。
- 矩阵运算系统要求如下:
(1) 能够按照给定的维度定义所需的矩阵,矩阵内容可通过初始化或复制同类变量或复制数组的形式获得;
(2) 系统必须能够计算二维矩阵的卷积运算,可通过类的成员函数或独立的函数实现;
(3) 系统必须能够对维度不匹配的矩阵运算做出提示,并保证系统不会因为此类违规而崩溃。
设计流程图
类功能及成员设计
类设计严格按照需求内容设计, 具体内容请看代码:
// Array 定义 一维数组
class Array {
private:
int size;
int* ptr;
public:
// 构造析构函数
Array(int size);
Array(const Array& second);
~Array();
// 修改器成员函数
void setup();
void setup(int* p);
Array operator+(const Array& second) const;
Array operator-(const Array& second) const;
int operator*(const Array& second) const;
Array operator*(int a) const;
void print() const;
};
// Matrix 定义 二维数组
class Matrix {
private:
int rowSize;
int colSize;
int** ptr;
public:
// 构造析构函数
Matrix(int rowSize, int colSize);
Matrix(const Matrix& second);
~Matrix();
// 修改器成员函数
void setup();
void setup(int *p);
Matrix conv(const Matrix& kernel) const; // 卷积计算
Matrix operator+(const Matrix& second) const;
Matrix operator-(const Matrix& second) const;
Matrix operator*(const Matrix& second) const;
Matrix operator*(int a) const;
void print() const;
};
设计方法描述
类的设计按照矩阵类的的行为及操作设计, 通过重载运算符计算矩阵的加\减及乘法, 通过重载实现不同方式的矩阵内容初始化。
测试用例及结果展示
二维矩阵的测试代码如下:
Matrix matrix1(3, 4);
matrix1.setup();
cout << "matrix1:" << endl;
matrix1.print();
Matrix matrix2(3, 4);
matrix2.setup();
cout << "matrix2:" << endl;
matrix2.print();
Matrix matrix3 = matrix1 + matrix2;
cout << "matrix3 = matrix1 + matrix2" << endl;
matrix3.print();
Matrix matrix4 = matrix1 - matrix2;
cout << "matrix4 = matrix1 - matrix2" << endl;
matrix4.print();
Matrix matrix5(4, 3);
matrix5.setup();
cout << "matrix5:" << endl;
matrix5.print();
Matrix matrix6 = matrix1 * matrix5;
cout << "matrix6 = matrix1 * matrix2" << endl;
matrix6.print();
Matrix matrix7 = matrix6 * 5;
cout << "matrix7 = matrix6 * 5" << endl;
matrix7.print();
int p[] = {1, 2, 3, 4};
cout << "list: " << endl;
for (int i = 0; i < 4; i++) {
cout << setw(5) << p[i];
}
cout << endl;
Matrix matrix8(2, 2);
matrix8.setup(p);
cout << "matrix8:" << endl;
matrix8.print();
二维矩阵的测试结果如下:
卷积计算的测试代码如下:
Matrix matrix(5, 5);
matrix.setup();
cout << "matrix:" << endl;
matrix.print();
Matrix kernel(3, 3);
kernel.setup();
cout << "kernel:" << endl;
kernel.print();
Matrix matrix2 = matrix.conv(kernel);
cout << "matrix2 = matrix.conv(kernel): " << endl;
matrix2.print();
结果如下:
一维矩阵的测试代码如下:
Array array1(6);
array1.setup();
cout << "array1:" << endl;
array1.print();
Array array2(6);
array2.setup();
cout << "array2:" << endl;
array2.print();
Array array3 = array1 + array2;
cout << "array3 = array1 + array2" << endl;
array3.print();
Array array4 = array1 - array2;
cout << "array4 = array1 - array2" << endl;
array4.print();
int a;
a = array1 * array2;
cout << "a = array1 * array2" << endl;
cout << setw(5) << a << endl;
Array array5 = array4 * 5;
cout << "array5 = array4 * 5" << endl;
array5.print();
Array array6(7);
array6.setup();
cout << "array6:" << endl;
array6.print();
int p[] = { 1, 2, 3, 4, 5 };
cout << "list: " << endl;
for (int i = 0; i < 5; i++) {
cout << setw(5) << p[i];
}
cout << endl;
Array array7(5);
array7.setup(p);
cout << "array7:" << endl;
array7.print();
总结及体会
本次项目中, 加深了我对类的构造和析构函数的理解, 在二维矩阵的析构操作时, 应该像下面这样对每一个二级指针释放, 并且在最后释放一级指针。
for (int i = 0; i < rowSize; i++) {
delete[] ptr[i];
}
delete[] ptr;
在从数组中取得二维数组值的功能的实现时, 因为一开始没办法知道二维数组的长度, 所以没办法直接传二维数组, 在经过一番思考后, 我想到了可以直接传等长的一维数组, 然后将其赋值的方法, 如下所示:
for (int i = 0; i < rowSize; i++) {
for (int j = 0; j < colSize; j++) {
ptr[i][j] = *(p + i * colSize + j);
}
}
`
在从数组中取得二维数组值的功能的实现时, 因为一开始没办法知道二维数组的长度, 所以没办法直接传二维数组, 在经过一番思考后, 我想到了可以直接传等长的一维数组, 然后将其赋值的方法, 如下所示:
for (int i = 0; i < rowSize; i++) {
for (int j = 0; j < colSize; j++) {
ptr[i][j] = *(p + i * colSize + j);
}
}
最后,我发现矩阵是没有除法的, 只有方阵才可以进行类似矩阵除法的操作, 因此我没有实现矩阵除法的运算, 与之同时, 我针对矩阵的点乘和乘法利用函数的重载分别做了实现, 后续可以继续实现更多的功能, 比如支持用户输入矩阵内容进行计算等等。