Решение СЛУ с помощью метода Якоби

Задача заключается в том, чтобы найти приближенное решение с помощью метода Якоби, но программа выводит нули и не продолжает итерацию, не понимаю как исправить эту ошибку.

#include <stdio.h>
double diff(int n, double x1[n], double x2[n]) {
    double s = 0;
    int i;
        for( i = 0; i < n; i++) {
            s += (x2[i]-x1[i]) * (x2[i]-x1[i]);
        }
        return s;
}
double jacobi(int n, double x1[n], double x2[n]) {
    int i, j;
    double s = 0, a[n][n], f[n];
        for(i = 0; i < n; i++) {
            for(j = 0; j < i-1; j++) {
                s += x1[j]*a[i][j];
            }
            for(j = i+1; j < n; j++) {
                s += x1[j]*a[i][j];
            }
            x2[i] = (f[i] - s) / a[i][i];
        }
}
int main () {
    int n, i, j, k;
    double eps;
    printf ("Add N:\n");
    scanf ("%d", &n);
    printf ("Add epsilon:\n");
    scanf("%lf", &eps);
    double a[n][n], f[n], x1[n], x2[n];
        for(i = 0; i < n; i++) {
            for(j = 0; j < n; j++) {
                scanf("%lf", &a[i][j]);
            }
        }
        for(i = 0; i < n; i++) {
            scanf ("%lf", &f[i]);
        }
        for(i = 0; i < n; i++) {
            x2[i] = 0;
        }
        while(diff(n, x1, x2) > eps*eps) {
            for(i = 0; i < n; i++) {
                x1[i] = x2[i];
            }
            jacobi(n, x1, x2);
        }
        for(i = 0; i < n; i++)
            printf ("%lf", x2[i]);
}
    

Ответы (1 шт):

Автор решения: Vladimir

Вы вводите матрицу в локальный массив a[n][n] в функции main(). Затем вызываете Вашу функцию jacobi(), в которой определен другой массив с именем a[n][n], который Вы и используете даже не проинициализировав. Поэтому и получаете нули (в этой последней матрице может быт любой мусор). Таким образом, даже если бы Вы сделали рабочую матрицу глобальным массивом, этот локальный в функции jacobi() с тем же именем всё портил. Вам нужно удалить этот последний массив, а рабочую матрицу нужно передавать параметром из функции main(). То есть нужно изменить: 1) удалить массив a[n][n] из функции jacobi(), 2) изменить заголовок этой функции, добавив в параметры массив a[n][n] и 3) исправить её вызов.

UPD: Программа не работает, потому что такая же ошибка была с вектором f[n] и еще одна ошибка - Вы не обнуляете заново сумму s для каждой строки матрицы (для каждого нового x2[i]).

И еще нужно главный цикл в main() (while(diff(n, x1, x2) > eps*eps)) сделать с пост-условием do ... while(), иначе Вы в него так и не зайдете.

После исправления ошибок, функция с методом Якоби должна выглядеть примерно так:

void jacobi(int n, double x1[n], double x2[n], double g[n], double m[n][n]) {
    double s = 0;
        for(int i = 0; i < n; i++) {
            s=0;
            for(int j = 0; j < i-1; j++) {
                s += x1[j]*m[i][j];
            }
            for(int j = i+1; j < n; j++) {
                s += x1[j]*m[i][j];
            }
            x2[i] = (g[i] - s) / m[i][i];
        } 
}

Я эту функцию сделал бы более компактно:

void jacobi(int n, double x1[n], double x2[n], double g[n], double m[n][n]) 
{
    double row[n];
    
    for(int i = 0; i < n; i++)
    {
        row[i] = g[i];
        for(int j = 0; j < n; j++)
            row[i] -= (i != j) ? m[i][j] * x1[j] : 0.0;             
        x2[i] = row[i] / m[i][i];
    }
}

Проверил, вроде бы оба варианта работают верно. И не забывайте, что метод Якоби будет сходиться далеко не для каждой матрицы.

→ Ссылка