2015-09-23 26 views
-1

我試圖將一個Matlab循環執行膽甾醇分解轉換爲C.我得到了正確的結果只是第一列。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 

錯誤在哪裏?

回答

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]; 
分別爲210

。 Matlab代碼中的轉置只會改變向量的方向,但不會切換參數或其他內容。

我建議你做一個計算點積的函數,這樣你可以重用代碼。

+0

我嘗試過,但我仍然沒有得到正確的結果 – Sinem

+0

我編輯我的答案。我不好意思立即看到這個:) – Wauzl

+0

謝謝,它現在正常工作! – Sinem

1

見代碼:

#include <iostream> 
#include <vector>  
#include <iostream> 
#include <math.h> 
using namespace std; 

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}; 
vector <vector<double> >L; 
int n=4; 
double calculateFunc1(int i){ 
double temp =0; 
for (int t = 0; t < n; t ++) 
    temp += L[i][t]*L[i][t]; 
return sqrt(M[i][i] - temp); 
} 

double calculateFunc2(int i,int j){ 
double temp =0; 
for (int t = 0; t < n; t ++) 
    temp += L[i][t]*L[j][t]; 
return (M[j][i] - temp)/L[i][i]; 
} 

int main() 
{ 
vector <double>temp; 
for (int i =0; i < n; i ++){ 
    for(int j =0; j < n; j ++){ 
     temp.push_back(0.0); 
    } 
    L.push_back(temp); 
    temp.clear(); 
} 

for(int i =0; i < n; i ++){ 
    L[i][i] = calculateFunc1(i); 

    for(int j= i +1 ; j < n; j++){ 
     L[j][i] = calculateFunc2(i,j); 
    } 
} 


for (int i=0;i<n;i++){ 

    for (int j=0;j<n;j++){ 
     cout<< L[i][j]<<" "; 
     } 
    cout << "\n"; 
} 
return 0; 
}