Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c中的Cholesky分解失败_C_Arrays_Pointers - Fatal编程技术网

c中的Cholesky分解失败

c中的Cholesky分解失败,c,arrays,pointers,C,Arrays,Pointers,我是c语言的新手,希望根据维基百科的伪代码实现cholesky分解。 需要动态分配ram 我使用以下示例矩阵尝试了我的代码: 4.000 2.000 0.000 0.000 2.000 5.000 2.000 0.000 0.000 2.000 10.000 3.000 0.000 0.000 3.000 2.000 这将导致: 2.000 0.000 0.000 0.000 1.000 2.000 0.000 0.000 0.000 1.000 3.000 0.

我是c语言的新手,希望根据维基百科的伪代码实现cholesky分解。 需要动态分配ram

我使用以下示例矩阵尝试了我的代码:

 4.000  2.000  0.000  0.000
 2.000  5.000  2.000  0.000
 0.000  2.000 10.000  3.000
 0.000  0.000  3.000  2.000
这将导致:

2.000 0.000 0.000 0.000
1.000 2.000 0.000 0.000
0.000 1.000 3.000 0.000
0.000 0.000 1.000 1.000
但我还是回来了

4.000 2.000 0.000  0.000 
0.000 5.000 2.000  0.000 
0.000 0.000 10.000 3.000 
0.000 0.000 0.000  2.000
我想我在使用指针时有些误解。我试图根据需求动态分配资源

谁能告诉我,为什么正确的值没有写入我的矩阵? 这是我的密码:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int Cholesky(int n, double **A){
    double sum;
    sum = 0.0f;
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < i; j++)
        {
            for(int k = 0; k < j-1; k++)
            {
                sum = sum - A[i][k]*A[j][k];
            }
            if(i > j)
            {
                A[i][j] = sum / A[j][j];
            } else
            {
                if(sum > 0)
                {
                    A[i][i] = sqrt(sum);
                } else {
                    printf("Die Matrix ist nicht symetrisch positiv\n");
                    return -1;
                }
            }
        }
    }

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++)
            printf("%.5f ", A[i][j]);
            printf("\n");
    }

}

int main(){
    int n = 4;
    double ** matrix;

    double test[4][4] = {{4.0f,2.0f,0.0f,0.0f},{2.0f,5.0f,2.0f,0.0f},{0.0f,2.0f,10.0f, 3.0f},{0.0f,0.0f,3.0f,2.0f}};

    /* Speicher reservieren für die int-Zeiger (=zeile) */
    matrix = malloc(n * sizeof(double *));
    if(NULL == matrix) {
       printf("Kein virtueller RAM mehr vorhanden ... !");
       return -1;
    }
    /* jetzt noch Speicher reservieren für die einzelnen Spalten
     * der i-ten Zeile */
    for(int i = 0; i < n; i++) {
        matrix[i] = malloc(n * sizeof(double));
        if(NULL == matrix[i]) {
            printf("Kein Speicher mehr fuer Zeile %d\n",i);
            return -1;
        }
    }
    /* mit beliebigen Werten initialisieren */
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            matrix[i][j] = test[i][j];

    /* Inhalt der Matrix entsprechend ausgeben */
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++)
            printf("%.5f ", matrix[i][j]);
            printf("\n");
    }

    Cholesky(n, matrix);

    /* Spalten der i-ten Zeile freigeben */
    for(int i = 0; i < n; i++)
        free(matrix[i]);
    /* Jetzt können die leeren Zeilen freigegeben werden. */
    free(matrix);
    int x;
    scanf("%d", x);
    return 0;
}

在调用Cholesky之前先打印矩阵,这就是打印原始矩阵的原因。

Cholesky算法是否正常工作

尝试将此作为函数的基础

 for (int i=0; i<n; i++) {
        chol[i][i] = A[i][i];
        for (int k=0; k<i; k++)
            chol[i][i] -= chol[k][i]*chol[k][i];
        chol[i][i] = sqrt(chol[i][i]);
        for (int j=i+1; j<n; j++) {
            chol[i][j] = A[i][j];
            for (k=0; k<i; k++)
                chol[i][j] -= chol[k][i]*chol[k][j];
            chol[i][j] /= chol[i][i];
        }
 }

例如,因为我讨厌数组的数组:

#include <malloc.h>
#include <math.h>

#define idx(A,i,j) A[i*n+j]

void Cholesky(int n, double *A)
{
    double *chol = (double *)calloc(sizeof(double) * n * n, 1);

    for (int i = 0; i<n; i++) {
        idx(chol, i, i) = idx(A, i, i);
        for (int k = 0; k<i; k++)
            idx(chol, i, i) -= idx(chol, k, i) * idx(chol, k, i);
        idx(chol, i, i) = sqrt(idx(chol, i, i));
        for (int j = i + 1; j<n; j++) {
            idx(chol, i, j) = idx(A, i, j);
            for (int k = 0; k<i; k++)
                idx(chol, i, j) -= idx(chol, k, i) * idx(chol, k, j);
            idx(chol, i, j) /= idx(chol, i, i);
        }
    }

    memcpy(A, chol, sizeof(double) * n * n);
    free(chol);
}

int main()
{
    double test[] = { 
        4.0f, 2.0f, 0.0f, 0.0f,
        2.0f, 5.0f, 2.0f, 0.0f,
        0.0f, 2.0f, 10.0f, 3.0f,
        0.0f, 0.0f, 3.0f, 2.0f };

    Cholesky(4, test);
}

动态分配的矩阵是正确的,指针的使用也是正确的

正确的值不会写入矩阵,因为用于cholesky分解的算法是错误的。您可以在此处找到正确的算法,例如:

您的函数仅在以下说明中修改矩阵:

if (i > j) A[i][j] = sum / A[j][j]; 
这意味着对角线下方的元素已归零,如您的帖子所示

4.000 2.000 0.000  0.000 
0.000 5.000 2.000  0.000 
0.000 0.000 10.000 3.000 
0.000 0.000 0.000  2.000

sum未初始化。@terrence hill,编译器是如何返回原始矩阵而不是垃圾矩阵的?单位化的总和会导致未定义的行为;编译器是不是跳过了所有的求和运算?也就是说,跳过整个for循环?好的,我现在用double sum初始化sum;总和=0.0f;但是仍然没有值写入我的矩阵。@Paul Ogilive我看不到malloc错误,所以我指出了我看到的错误。如果将sum的值从0更改为100,则会看到矩阵值发生更改。我怀疑算法中有错误。ifi>j是不变的/真的,由forint j=0引起;j