ibeautiful
看来您可能在第一个内层for循环方面犯了一些缩进错误:U必须在之前进行评估L;您也没有正确计算求和项acc,也没有正确地将对角项设置L为 1。在进行一些其他语法修改后,您可以按如下方式重写您的函数:def LUDecomposition(A): n = A.shape[0] L = np.zeros((n,n), np.float64) U = np.zeros((n,n), np.float64) for i in range(n): # U for k in range(i,n): s1 = 0 # summation of L(i, j)*U(j, k) for j in range(i): s1 += L[i,j]*U[j,k] U[i,k] = A[i,k] - s1 # L for k in range(i,n): if i==k: # diagonal terms of L L[i,i] = 1 else: s2 = 0 # summation of L(k, j)*U(j, i) for j in range(i): s2 += L[k,j]*U[j,i] L[k,i] = (A[k,i] - s2)/U[i,i] return L, U与scipy.linalg.lu作为可靠参考A相比,这一次给出了矩阵的正确输出:import numpy as npfrom scipy.linalg import luA = np.array([[-4, -1, -2], [-4, 12, 3], [-4, -2, 18]])L, U = LUDecomposition(A)P, L_sp, U_sp = lu(A, permute_l=False)P>>> [[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])L>>> [[ 1. 0. 0. ] [ 1. 1. 0. ] [ 1. -0.07692308 1. ]]np.allclose(L_sp, L))>>> TrueU>>> [[-4. -1. -2. ] [ 0. 13. 5. ] [ 0. 0. 20.38461538]]np.allclose(U_sp, U))>>> True注意:与 scipy lapack getrf 算法不同,此 Doolittle 实现不包括旋转,这两个比较只有在P返回的置换矩阵scipy.linalg.lu是单位矩阵时才为真,即scipy 没有执行任何置换,这确实是您的矩阵的情况A. 在 scipy 算法中确定的置换矩阵旨在优化结果矩阵的条件数,以减少舍入误差。最后,您可以简单地验证一下A = LU,如果分解正确,情况总是如此:A = np.random.rand(10,10)L, U = LUDecomposition(A)np.allclose(A, np.dot(L, U))>>> True尽管如此,就数值效率和准确性而言,我不建议您使用自己的函数来计算 LU 分解。希望这可以帮助。