3x3矩阵行列式函数

2024-05-03 07:13:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在写一个更大的程序,尽快得到3x3矩阵的行列式对它的正常工作是非常重要的。我读到过我可以用numPy来做这件事,但我想也许写我自己的代码会比我在CompSci的第三个学期更有教育意义。

所以我写了两个函数,我使用time.clock()(我在win7机器上)来计算每个函数返回一个值需要多长时间。

这是第一个功能:

def dete(a):
   x = (a[0][0] * a[1][1] * a[2][2]) + (a[1][0] * a[2][1] * a[3][2]) + (a[2][0] * a[3][1] * a[4][2])
   y = (a[0][2] * a[1][1] * a[2][0]) + (a[1][2] * a[2][1] * a[3][0]) + (a[2][2] * a[3][1] * a[4][0])
   return x - y

这是第二个功能:

def det(a):
    a.append(a[0]); a.append(a[1]);
    x = 0
    for i in range(0, len(a)-2):
        y=1;        
        for j in range(0, len(a)-2):    
            y *= a[i+j][j]      
        x += y

    p = 0
    for i in range(0, len(a)-2):
        y=1;
        z = 0;
        for j in range(2, -1, -1):  
            y *= a[i+z][j]  
            z+=1        
        z += 1
        p += y  
    return x - p

他们都给出了正确的答案,但是第一个似乎更快,这让我认为,因为for循环使用起来更优雅,通常更快,我做错了什么-我使循环太慢和太胖。我试着把它剪下来,但似乎*=和+=操作花费了太多时间,它们太多了。 我还没有检查numPy处理这个问题的速度,但是我想更好地编写高效的代码。 有什么办法让这些循环更快的吗?


Tags: 函数代码in程序功能numpyforlen
3条回答

首先让我注意到,微观速度优化应该在另一种语言中进行。因此,最好使用使用使用c编写功能的库。

关于for循环: 为了加速,展开(小)循环是一种常见的技术,因此让循环来完成任务并不总是更快。通常它只是更通用(而且大多数通用算法实际上比专用算法慢)。

如注释中所述,当用*替换-时,它不会提高python的速度,但是如果涉及的算术操作更少,它可能会提高速度。因此,我将在此处发布计算出的术语:

def dete(a):
    return (a[0][0] * (a[1][1] * a[2][2] - a[2][1] * a[1][2])
           -a[1][0] * (a[0][1] * a[2][2] - a[2][1] * a[0][2])
           +a[2][0] * (a[0][1] * a[1][2] - a[1][1] * a[0][2]))

正如你所看到的,有5+/-和9*,在原始版本中有5+/-和12*。还要注意,这个版本访问a只有15次,而原来的版本访问了18次。

总结一下,这产生了3个算术运算和3个变量访问小于完全乘法版本。

循环更优雅、更通用,但它们“通常不会比单个表达式中的两个内联乘法更快”。

首先,python中的一个for循环必须根据uyou将交互的方式(对range的调用)来组装对象,然后对循环中的每个项调用迭代器上的一个方法。

所以,取决于你在做什么,如果内联表单足够快,你可以保留它-如果它仍然太慢(就像我们在Python中进行数值计算时通常的情况),你应该使用一个数字库(例如NumpY),它可以在本机代码中计算行列式。在这种数字操作代码的情况下,您可以使用本机代码使其运行速度提高数百倍。

如果yo9u需要一些已经生成的库无法执行的数值计算,如果您寻求速度(例如,图像处理中的像素操作),您可能希望编写一个运行在本机代码中的扩展(使用C、Cython或其他东西),以便快速完成它。

另一方面,如果速度不是关键,而且您甚至注意到内联表达式只是“稍微快一点”,那么只需使用完整的循环——您可以获得更可读和可维护的代码——这毕竟是使用Python的主要原因。

在您给出的特定示例中,可以通过对元组的“range”调用进行硬编码来提高循环代码的速度—例如,更改: for i in range(0, len(a)-2):for i in (0, 1, 2)注意,与内联情况一样,您失去了处理不同大小矩阵的能力。

当您展开它时,如上面所建议的,您也可以将两个块合并为一个,因为快速浏览发现两个块之间没有依赖关系(如果我错了,请纠正我)

相关问题 更多 >