Или я чего-то не понимаю, или что-то не так.
Итак, есть задача. Решить СЛУ (систему линейных уравнений) методом Гаусса (последовательного исключения переменных).
Задаю через текстовый файл два массива (один двумерный, главная матрица, и один одномерный).
Первый - это коэффициенты при x, а второй - свободные члены.
Допустим, уравнение вот такого вида:
a[0][0]x[0]+a[0][1]x[1]+...+a[0][n-1]x[n-1]=b[0]
...
a[n-1][0]x[0]+a[n-1]x[1]+...+a[n-1][n-1]x[n-1]=b[n-1]Вот a - двумерный массив, b - одномерный.
Функция выглядит вот так:
double *gauss(int n, double **a, double *b) {
int i,j,k;
double minus;
// строки i,j, столбцы k
for (i=0; i!=n-1; i++) // исключаем переменную при a[i][i]
for (j=i+1; j!=n; j++) { // из каждого уравения, начиная с a[j][k]
for (k=0; k!=n; k++) { // для k-го столбца
printf("a[%d][%d]=%lf\n",j,k,a[j][k]);
minus=a[i][k]*a[j][i]/a[i][i];
printf("minus=%lf\n",a[i][k]*a[j][i]/a[i][i]);
/*a[j][k]=a[j][k]-minus;*/
printf("a[%d][%d]=%lf\n",j,k,a[j][k]);
}
b[i]-=a[i][k]*a[j][i]/a[i][i];
}
for (i=0; i!=n; i++) {
for (j=0; j!=n; j++)
printf("%lf*x%d + ",a[i][j],j);
printf("= %lf\n",b[i]);
}
}
Входные параметры - количество уравнений/корней (для простоты предположим, что переменных и уравнений одинаково, и решения всегда есть), и два массива - коэффициенты и свободные члены.
Так вот. Что меня просто заставило поделить на 0 много раз. :o :O oO :[
Если в таком виде - то выводит:
a[1][0]=4.000000
minus=4.000000
a[1][0]=4.000000
a[1][1]=5.000000
minus=8.000000
a[1][1]=5.000000
a[1][2]=6.000000
minus=12.000000
a[1][2]=6.000000
a[2][0]=7.000000
minus=7.000000
a[2][0]=7.000000
a[2][1]=3.000000
minus=14.000000
a[2][1]=3.000000
a[2][2]=1.000000
minus=21.000000
a[2][2]=1.000000
a[2][0]=7.000000
minus=2.400000
a[2][0]=7.000000
a[2][1]=3.000000
minus=3.000000
a[2][1]=3.000000
a[2][2]=1.000000
minus=3.600000
a[2][2]=1.000000
1.000000*x0 + 2.000000*x1 + 3.000000*x2 + = 4.000000
4.000000*x0 + 5.000000*x1 + 6.000000*x2 + = 3.000000
7.000000*x0 + 3.000000*x1 + 1.000000*x2 + = 2.000000(ну это типа для отладки я сделал столько вывода.
Сначала пишется старое значение, потом сколько надо вычесть, а потом результат. Здесь просто закомментировано собственно вычитание, потому старое и новое значение совпадает.
Так вот, если раскомментировать строку
/*a[j][k]=a[j][k]-minus;*/которая собственно и занимается нужным мне вычитанием - то значение minus тоже меняется! и становится равным нулю везде, кроме первого столбца!!! Почему программа себя так ведёт? Ведь значение minus в этой строке меняться не должно! Или я чего-то неправильно понимаю?
Вот такой вывод:
a[1][0]=4.000000
minus=4.000000
a[1][0]=0.000000
a[1][1]=5.000000
minus=0.000000
a[1][1]=5.000000
a[1][2]=6.000000
minus=0.000000
a[1][2]=6.000000
a[2][0]=7.000000
minus=7.000000
a[2][0]=0.000000
a[2][1]=3.000000
minus=0.000000
a[2][1]=3.000000
a[2][2]=1.000000
minus=0.000000
a[2][2]=1.000000
a[2][0]=0.000000
minus=0.000000
a[2][0]=0.000000
a[2][1]=3.000000
minus=3.000000
a[2][1]=0.000000
a[2][2]=1.000000
minus=0.000000
a[2][2]=1.000000
1.000000*x0 + 2.000000*x1 + 3.000000*x2 + = 4.000000
0.000000*x0 + 5.000000*x1 + 6.000000*x2 + = 3.000000
0.000000*x0 + 0.000000*x1 + 1.000000*x2 + = 2.000000Целиком исходник выглядит так:
#include <stdio.h>
#include <stdlib.h>
double *gauss(int n, double **a, double *b) {
int i,j,k;
double minus;
// строки i,j, столбцы k
for (i=0; i!=n-1; i++) // исключаем переменную при a[i][i]
for (j=i+1; j!=n; j++) { // из каждого уравения, начиная с a[j][k]
for (k=0; k!=n; k++) { // для k-го столбца
printf("a[%d][%d]=%lf\n",j,k,a[j][k]);
minus=a[i][k]*a[j][i]/a[i][i];
printf("minus=%lf\n",a[i][k]*a[j][i]/a[i][i]);
a[j][k]=a[j][k]-minus;
printf("a[%d][%d]=%lf\n",j,k,a[j][k]);
}
b[i]-=a[i][k]*a[j][i]/a[i][i];
}
for (i=0; i!=n; i++) {
for (j=0; j!=n; j++)
printf("%lf*x%d + ",a[i][j],j);
printf("= %lf\n",b[i]);
}
}
int main(int argc, char *argv[]) {
if (argc!=2) {
printf("Введите ./kram matrix.txt\n");
return 0;
}
FILE *f=fopen(argv[1],"r");
if (!f) {
printf("Файл не найден.\n");
return 0;
}
int n;
fscanf(f,"%d",&n);
int i,j;
double **a;
double *b;
b=malloc(sizeof(double)*n);
a=malloc(sizeof(double*)*n);
for (i=0; i!=n; i++) {
a[i]=malloc(sizeof(double)*n);
for (j=0; j!=n; j++)
fscanf(f,"%lf ",&a[i][j]);
fscanf(f,"%lf\n",&b[i]);
}
double *x;
x=gauss(n,a,b);
/*for (i=0; i!=n; i++) {*/
/*for (j=0; j!=n; j++)*/
/*printf("%lf*x%d + ",a[i][j],j);*/
/*printf("= %lf\n",b[i]);*/
/*}*/
/*for (i=0; i!=n; i++)*/
/*printf("x%d=%lf\n",i,x[i]);*/
fclose(f);
/*for (i=0; i!=n; i++) free(a[i]);*/
/*free(a);*/
return 0;
}