Решение СЛУ с помощью метода Якоби
Задача заключается в том, чтобы найти приближенное решение с помощью метода Якоби, но программа выводит нули и не продолжает итерацию, не понимаю как исправить эту ошибку.
#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 шт):
Вы вводите матрицу в локальный массив 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];
}
}
Проверил, вроде бы оба варианта работают верно. И не забывайте, что метод Якоби будет сходиться далеко не для каждой матрицы.