我试图将执行cholesky分解的Matlab循环转换为C.我只为第一列得到了正确的结果。
Matlab代码:
M = [5 1.2 0.3 -0.6; 1.2 6 -0.4 0.9; 0.3 -0.4 8 1.7; -0.6 0.9 1.7 10];
n = length( M );
L = zeros( n, n );
for i=1:n
L(i, i) = sqrt( M(i, i) - L(i, :)*L(i, :)' );
for j=(i + 1):n
L(j, i) = ( M(j, i) - L(i, :)*L(j, :)' )/L(i, i);
end
end
我的C代码:
int main()
{
double M[4*4]={5, 1.2, 0.3, -0.6, 1.2, 6, -0.4, 0.9, 0.3, -0.4, 8, 1.7, -0.6, 0.9, 1.7, 10};
int n=4;
double L[4*4]={0};
double sum;
for (int i=0;i<n;i++){
sum=0;
for (int j=0;j<n;j++){
sum+=L[i*n+j]*L[j*n+i];
}
L[i*n+i]=sqrt(M[i*n+i]-sum);
for (int j=i+1;j<n;j++){
sum=0;
for(int k=0;k<n;k++){
sum+=L[i*n+k]*L[k*n+j];
}
L[j*n+i]=(M[j*n+i]-sum)/L[i*n+i];
}
}
return 0;
}
Matlab的结果是:
L =
2.2361 0 0 0
0.5367 2.3900 0 0
0.1342 -0.1975 2.8183 0
-0.2683 0.4368 0.6466 3.0527
但在C中,结果是:
L_c =
2.2361 0 0 0
0.5367 2.4495 0 0
0.1342 -0.1633 2.8284 0
-0.2683 0.3674 0.6010 3.1623
错误在哪里?
答案 0 :(得分:1)
检查线
sum+=L[i*n+j]*L[j*n+i];
和
sum+=L[i*n+k]*L[k*n+j];
我认为这应该是
sum+=L[i*n+j]*L[i*n+j];
和
sum+=L[i*n+k]*L[j*n+k];
分别。 Matlab代码中的转置只是改变了向量的方向,但没有切换参数或其他东西。
我建议你制作一个计算点积的函数,这样你就可以重用代码了。
答案 1 :(得分:1)
参见守则:
{{1}}