【问题标题】:Python 3 - IndexError: list index out of range when trying to find determinant of a matrixPython 3 - IndexError:尝试查找矩阵的行列式时列出索引超出范围
【发布时间】:2016-08-02 07:14:36
【问题描述】:

我正在尝试使用表示二维矩阵的嵌套列表来查找行列式。但它无限调用 getMinor() 函数并不断从同一个列表中删除,这不应该发生,因为我每次都在创建新列表。下面是代码。此外,所有函数都定义在一个名为 'Matrix()' 的类中。

def __init__(self):
    self.matrix_list = []
    self.no_of_row = 0
    self.no_of_col = 0

def getMinor(self, matrix, j):
    del matrix[0]
    for i in range(len(matrix)):
        del matrix[i][j]

    m = Matrix()
    m.matrix_list = matrix[:]
    m.no_of_row = len(m.matrix_list)
    #print(m.no_of_row)
    print(m.matrix_list)
    m.no_of_col = len(m.matrix_list[0])
    return m.detMatrix()

def detMatrix(self):
    if self.no_of_row == 2 and self.no_of_col == 2:
        return self.matrix_list[0][0] * self.matrix_list[1][1] - self.matrix_list[0][1] * self.matrix_list[1][0]
    else:
        matrix = self.matrix_list[:]
        det = 0
        for i in range(self.no_of_col):
            det += ((-1)**i) * self.matrix_list[0][i] * self.getMinor(matrix, i)
        return det

【问题讨论】:

  • 切片只做浅拷贝。你需要更深层次的东西。
  • 我正在考虑 - 类 Matrix 有两种方法 - getMinor 和 detMatix。那么你在它的方法中制作这个类的对象吗?示例:getMinor() 中的“m=Matrix()”。只是这样还是识别问题?
  • @DineshPundkar 它不是识别问题,我正在 getMinor 中制作类的对象来调用 detMatrix

标签: python python-3.x math matrix


【解决方案1】:

你有两个问题。不幸的是,user2357112 提到了一个,他没有费心解释。当您使用表达式 x[:] 时,您会得到列表 x 的浅表副本。深拷贝和浅拷贝之间通常没有实际区别;例如,如果 x 包含数字或字符串。但是在您的情况下, x 的元素是列表。新列表中的每个元素 x[:] 将与原始 x 中的子列表相同,而不是副本。当您删除这些嵌套列表中的一个元素(del matrix[i][j])时,您将删除一些原始数据。

第二个问题是您没有正确处理递归。在函数 detMatrix 中创建一个新变量矩阵。即使您在这里进行深层复制,也无法解决问题。您将矩阵传递给 getMinor,它会从中删除一些数据。现在,在 for 循环的下一步中,您已经弄乱了数据。您需要在 getMinor 函数内部进行深层复制。

这是一个至少可以运行的程序。我没有检查你的代数:-)

我还要补充一点,它的效率非常低。制作副本然后从副本中删除片段的想法没有多大意义。我没有解决这个问题。

import copy
class Matrix:
    def __init__(self):
        self.matrix_list = []
        self.no_of_row = 0
        self.no_of_col = 0

    def getMinor(self, matrix_list, j):
        print("Entry:", matrix_list)
        matrix = copy.deepcopy(matrix_list)
        del matrix[0]
        for i in range(len(matrix)):
            del matrix[i][j]
        print("After deletions", matrix_list)

        m = Matrix()
        m.matrix_list = matrix[:]
        m.no_of_row = len(m.matrix_list)
        m.no_of_col = len(m.matrix_list[0])
        x = m.detMatrix()
        print(m.matrix_list, m.no_of_row, m.no_of_col)
        return x

    def detMatrix(self):
        if self.no_of_row == 2 and self.no_of_col == 2:
            return self.matrix_list[0][0] * self.matrix_list[1][1] - self.matrix_list[0][1] * self.matrix_list[1][0]
        else:
            det = 0
            for i in range(self.no_of_col):
                det += ((-1)**i) * self.matrix_list[0][i] * self.getMinor(self.matrix_list, i)
            return det

m = Matrix()
m.matrix_list.append([0.0,1.0,2.0,3.0])
m.matrix_list.append([1.0,2.0,3.0,4.0])
m.matrix_list.append([2.0,3.0,4.0,5.0])
m.matrix_list.append([3.0,5.0,7.0,9.0])
m.no_of_row = 4
m.no_of_col = 4

print(m.detMatrix())

【讨论】:

  • 像魔术一样工作。通过制作副本然后从副本中删除,我试图将实际数据与递归/函数调用中传递的数据隔离开来。我知道问题是因为同一个列表一次又一次地被编辑,我能弄明白的就这么多。还请指出任何其他效率低下的地方,因为您现在可能已经猜到我是初学者级别的 Python 程序员。也很抱歉,我不能投票给答案,因为我的声誉低于 15,因为我是新来的。
  • @Divyanshu 我可以,但请将您的代码移至codereview.stackexchange.com,并在那里询问您关于风格、组织、效率等方面的问题。
猜你喜欢
  • 2017-02-12
  • 1970-01-01
  • 2017-04-20
  • 2012-11-26
  • 1970-01-01
  • 2023-04-11
  • 2018-03-19
  • 1970-01-01
  • 2016-08-25
相关资源
最近更新 更多