KMatrix的设计与实现
1. 任务要求
使用python编写二维矩阵KMatrix类,要求如下:
KMatrix可以存储int/double等常规数值类型,同一个矩阵内部存储的数据类型是一致的;
实现KMatrix的初始化函数 ;
实现KMatrix获取行数、列数的函数
实现Kmatrix中某个元素修改与获取函数
实现KMatrix的加(+)、减(-)、乘(*) 运算, 使用运算符重载实现;
实现KMatrix的输出
2. 设计思路
矩阵存储方式:
使用python列表存储比较合适,可以方便操作,将矩阵数据以list的形式放入KMatrix的matrix成员中
类标识符
标识符 | 值 | 含义 |
OP_ADD_CODE | 0 | 加法操作 |
OP_SUB_CODE | 1 | 减法操作 |
OP_MUL_CODE | 2 | 乘法操作 |
MAT_DATA_TYPE_INT | 0 | 矩阵元素类型整型 |
MAT_DATA_TYPE_FLOAT | 0 | 矩阵元素类型浮点型 |
MAT_DATA_TYPE_UNK | 0 | 矩阵元素类型未知 |
运算符重载:
def __add__(self, other): 对加号进行运算符重载,要注意判断other为KMatrix类型,对其行列,将对应行和对应列的元素相加,生成同型结果矩阵返回
def __sub__(self, other): 对减号进行运算符重载,要注意判断other为KMatrix类型,对其行列,将对应行和对应列的元素相减,生成同型结果矩阵返回
def __mul__(self, other): 对乘号运算符进行重载,要注意判断other为KMatrix类型,self矩阵的列数要与other的行数相同,否则无法进行乘操作,模拟手算的过程,生成以self行数为行、other列数为列的矩阵返回。
输出重载:
def __str__(self):
对输出进行重写,print时格式化输出。
自定义异常:
KMatrixException
异常基类
ElementUnionError
矩阵元素数据类型不统一异常,将抛出第一个类型不符合的元素索引位置
OperationError
矩阵运算操作异常
3. 源码实现
""" KMatrix 实现矩阵基本运算 :Author TianChanghang :Date 2022.7.10 :CSDN Moresweet """ class KMatrix: OP_ADD_CODE = 0 OP_SUB_CODE = 1 OP_MUL_CODE = 2 MAT_DATA_TYPE_INT = 0 MAT_DATA_TYPE_FLOAT = 1 MAT_DATA_TYPE_UNK = -1 def __init__(self, data): """ :description : This method receive a list object to create a instance with Matrix. :param data: list :exception ElementUnionError: To throw exception when data type are different and show the first invalid element index. """ self.isTypeValid = True self.col = 0 self.row = 0 self.matrix = [] errRow = -1 errCol = -1 if isinstance(data[0][0], int): for rowList in data: errRow += 1 errCol = -1 for element in rowList: errCol += 1 if not isinstance(element, int): self.isTypeValid = False self.dataType = KMatrix.MAT_DATA_TYPE_UNK break else: continue break self.dataType = KMatrix.MAT_DATA_TYPE_INT if isinstance(data[0][0], float): for rowList in data: errRow += 1 errCol = -1 for element in rowList: errCol += 1 if not isinstance(element, float): self.isTypeValid = False self.dataType = KMatrix.MAT_DATA_TYPE_UNK break else: continue break self.dataType = KMatrix.MAT_DATA_TYPE_FLOAT if self.isTypeValid: self.matrix = data self.row = len(self.matrix) self.col = len(self.matrix[0]) else: # if errCol - 1 < 0: # errCol = len(data[0]) # errRow -= 1 raise ElementUnionError(errRow, errCol) def __add__(self, other): if self.checkOpValid(other, KMatrix.OP_ADD_CODE): resList = other.matrix for row in range(len(self.matrix)): for col in range(len(self.matrix[0])): resList[row][col] = self.matrix[row][col] + other.matrix[row][col] return KMatrix(resList) else: raise OperationError("Operation invalid") def __sub__(self, other): if self.checkOpValid(other, KMatrix.OP_SUB_CODE): resList = other.matrix for row in range(len(self.matrix)): for col in range(len(self.matrix[0])): resList[row][col] = self.matrix[row][col] - other.matrix[row][col] return KMatrix(resList) else: raise OperationError("Operation invalid") def __mul__(self, other): """ :description : Matrix dot multiple method (reload operator *) :param other: operation KMatrix object :return:result KMatrix object """ resList = [] if self.checkOpValid(other, KMatrix.OP_MUL_CODE): tempList = [] for row in range(len(self.matrix)): for col in range(len(other.matrix[0])): tempAnsVal = 0 rightMatIndex = 0 for leftMatElement in self.matrix[row]: tempAnsVal += leftMatElement * other.matrix[rightMatIndex][col] rightMatIndex += 1 tempList.append(tempAnsVal) resList.append(tempList) tempList = [] return KMatrix(resList) else: raise OperationError("Operation invalid") def __str__(self): resStr = "" printIndex = 0 for rowList in self.matrix: if printIndex == 0: resStr += "|" else: resStr += "|\n|" for element in rowList: resStr += "{:^10}".format(element) printIndex += 1 resStr += "|" return resStr def checkOpValid(self, other, opType): """ :description: To check the validation of different operation's object. :param other: KMatrix object :param opType: Operation type :return: Boolean """ if opType == KMatrix.OP_ADD_CODE and \ isinstance(other, KMatrix) and \ self.row == other.row and \ self.col == other.col: pass elif opType == KMatrix.OP_SUB_CODE and \ isinstance(other, KMatrix) and \ self.row == other.row and \ self.col == other.col: pass elif opType == KMatrix.OP_MUL_CODE and \ isinstance(other, KMatrix) and \ self.col == other.row: pass else: return False return True def modfiyElement(self, row, col, val): if row > self.row or col > self.col or row < 0 or col < 0 or isinstance(row, float) or isinstance(col, float): raise OperationError("Index over range") if (isinstance(val, int) and self.dataType == KMatrix.MAT_DATA_TYPE_INT) or \ (isinstance(val, float) and self.dataType == KMatrix.MAT_DATA_TYPE_FLOAT): self.matrix[row][col] = val else: raise OperationError("Element Value Type Invalid") def getMatrixRow(self): return self.row def getMatrixCol(self): return self.col def getElementValue(self, row, col): return self.matrix[row][col] class KMatrixException(Exception): """ :description : KMatrix exception """ pass class ElementUnionError(KMatrixException): """ :description :Exception of matrix element's inconsistency type """ def __init__(self, row, col): self.expCol = col self.expRow = row def __str__(self): return "KMatrix Type Union Error : Error Element Index [{}][{}]".format(self.expRow, self.expCol) class OperationError(KMatrixException): def __init__(self, msg): self.msg = msg def __str__(self): return self.msg
4. 运行结果示例
测试方法
if __name__ == '__main__': TTT = KMatrix([[2, 2], [1, 1]]) * KMatrix([[3, 5, 2], [6, 2, 9]]) print(TTT) A = KMatrix([[4, 2, 88], [1, 9, 5], [9, 33, 14]]) ele = A.getElementValue(1, 2) B = KMatrix([[7, 4, 2], [4, 8, 15], [2, 7, 11]]) C = KMatrix([[2.1, 2.4, 0.9], [4.1, 8.5, 1.2], [2.0, 7.1, 11.7]]) D = KMatrix([[9.1, 7.3, 4.3], [5.5, 7.2, 8.1], [7.3, 6.1, 9.55]]) G = KMatrix([[7], [4], [2]]) E = A + B print(E) F = C - D P = A * G print(P) K = C * D print(K) A.modfiyElement(1, 1, 2) print(A) print("G col is : {}".format(G.getMatrixCol())) print("G row is : {}".format(G.getMatrixRow())) M = D * G print(M) L = G * D print(L)
运行结果
| 18 14 22 | | 9 7 11 | | 11 6 90 | | 5 17 20 | | 11 40 25 | | 212 | | 53 | | 223 | |-22.830000000000002-6.270000000000001 -21.765 | |-46.959999999999994-7.840000000000001 -70.01 | |-85.9499999999999911.129999999999997-30.63500000000001| | 4 2 88 | | 1 2 5 | | 9 33 14 | G col is : 1 G row is : 3 |-75.39999999999999| |-18.400000000000002| |-28.800000000000004| Traceback (most recent call last): File "E:\PyProjects\MatrixCal\MatirixCal.py", line 216, in <module> L = G * D File "E:\PyProjects\MatrixCal\MatirixCal.py", line 107, in __mul__ raise OperationError("Operation invalid") __main__.OperationError: Operation invalid