Ошибка в программе для решения СЛАУ методом Гаусса - C (СИ)
Формулировка задачи:
Здравствуйте помогите пожалуйста!
Не могу найти ошибку в программе
Алгоритм такой: среди элементов первого столбца матрицы выбираю ненулевой, перемещаю его на крайнее верхнее положение перестановкой строк и вычитаю получившуюся после перестановки первую строку из остальных строк, домножив её на величину, равную отношению первого элемента каждой из этих строк к первому элементу первой строки, обнуляя тем самым столбец под ним.
При решении СЛАУ 3-го порядка:
1 2 3 3
3 5 7 0
1 3 4 1
матрица приведенная к треугольному виду:
1 2 3 3
0 1 2 9
0 0 1 11
корни -14; -13; 11 все в порядке
а если случай множества решений
исходная матрица:
1 -2 0 1 -3
3 -1 -3 0 1
2 1 -2 -1 4
1 3 -2 -2 7
Матрица приведенная к треугольному виду:
1 -2 0 1 -3
0 1 -0.6 -0.6 2
0 0 1 0 0
0 0 0 1 0
почему то в нижних двух строках матрицы 1-цы хотя должны быть нули
//Решение системы линейных уравнений методом Гаусса
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <windows.h>
#define N 10
void main()
{
SetConsoleCP (1251);//для правильного отображения русского шрифта в консоли
SetConsoleOutputCP (1251);//для правильного отображения русского шрифта в консоли
system("cls");//производит очистку экрана
float t, a[N][N + 1], x[N];//x[N]-корни системы;
int i, j, k, n, count = 0;//j - номер строки, i - номер столбца;
bool f = false;
do
{
printf("Введите размерность матрицы:\n");
scanf("%d", &n);
if(n>N)
printf("Слишком большое число уравнений. Повторите ввод.\n");
else
printf("N = %d\n",n);
}
while(n>N);
printf("Введите СЛАУ:\n");//ввод исходных данных
for(j = 0; j < n; j++)
for(i = 0; i < n + 1; i++)
{
printf("a[%d][%d] = ",j,i);
scanf("%f", &a[j][i]);
count++;
if(count == (n + 1))
printf("\n",count=0);
}
system("cls");
printf("Исходная матрица:\n");//вывод данных на экран
for(j = 0; j < n; j++)
{
for(i = 0; i < n + 1; i++)
printf("%6.3f\t",a[j][i]);
printf("\n");
}
//проверка на бесконечное множество решений
for(j = 0; j < n; j++)//проверка системы уравнений, а[0][0] не должен быть 0
{
if(fabs(a[j][j]) < 0.0001)
{
f = true;
}
else if(a[j][j] == 0)
{
k = j;//запоминаем адрес строки;
while((a[k+1][i] == 0) && (k < n))//если 0 изменяем порядок уравнений
k++;
if(a[k+1][i] != 0)
{
for(i = 0; i < n + 1; i++)
{
t = a[j][i];
a[j][i] = a[k+1][i];
a[k+1][i] = t;
}
//вывод полученной матрицы
for(j = 0; j < n; j++)
{
for(i = 0; i < n + 1; i++)
printf("%6.3f\t",a[j][i]);
printf("\n");
}
}
else
{
f = true;//если по диаганали нули
}
}
}
//прямой ход
for(k = 0; k < n; k++)
{
for(j = n; j >= k; j--)
a[k][j] = a[k][j]/a[k][k];//делим на коэффиц. a[1][1],a[2][2] и т.д.
for(i = k + 1; i < n; i++)
for(j = n; j >= k; j--)
a[i][j] = a[i][j] - a[i][k]*a[k][j];//вычитаем из 2 ур-ия 1-ое умнож. на коэфф. и т.д.
}
/*
//проверка системы
for( j = 0; j < n; j++ )
{
count = 0;
for(i = 0; i < n; i++)
{
if(a[j][i] == 0)
count++;
printf("кол-во нулей: %d",);
if(count == (n - 1) && a[j][n] == 0)//если коэфф. в строке = 0 и своб. член = 0
printf("СЛАУ не имеет решений\n");
else if (count == (n - 1) && a[j][n] != 0)//если коэфф. в строке = 0 и своб. член не равен 0
f = true;// имеет множество решений
}
}
*/
//обратный ход
for(i = 0; i < n; i++)
x[i] = a[i][n];
for(i = n-2; i >= 0; i--)
for(j = i+1; j < n; j++)
x[i] = x[i] - x[j]*a[i][j];//находим корни
if(f == false)
{
//вывод матрицы треугольного вида
printf("Матрица приведенная к треугольному виду:\n");
for(j = 0; j < n; j++)
{
for(i = 0; i < n + 1; i++)
printf("%6.3f\t",a[j][i]);
printf("\n");
}
//вывод решения
printf("Корни СЛАУ:\n");
for(i = 0; i < n; i++)
printf("x[%d] = %6.3f\n",i,x[i]);
}
else
printf("Система имеет множество решений\n");
}Решение задачи: «Ошибка в программе для решения СЛАУ методом Гаусса»
textual
Листинг программы
//Решение системы линейных уравнений методом Гаусса с выбором главного элемента по столбцу
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <math.h>
#include <windows.h>
#define N 10
int main(void)
{
SetConsoleCP (1251);//для правильного отображения русского шрифта в консоли
SetConsoleOutputCP (1251);//для правильного отображения русского шрифта в консоли
system("cls");//производит очистку экрана
float t, a[N][N + 1], x[N];//x[N]-корни системы;
int i, j, k, n, j_max, count = 0;//j - номер строки, i - номер столбца;
//ввод размерности матрицы
do
{
printf("Введите размерность матрицы:\n");
scanf("%d", &n);
if(n>N)
printf("Слишком большое число уравнений. Повторите ввод.\n");
else
printf("N = %d\n",n);
}
while(n>N);
//ввод СЛАУ
printf("Введите СЛАУ:\n");//ввод исходных данных
for(j = 0; j < n; j++)
for(i = 0; i < n + 1; i++)
{
printf("a[%d][%d] = ",j,i);
scanf("%f", &a[j][i]);
count++;
if(count == (n + 1))
printf("\n",count=0);
}
system("cls");//очистка экрана
//вывод данных на экран
printf("Исходная матрица:\n");
for(j = 0; j < n; j++)
{
for(i = 0; i < n + 1; i++)
printf("%6.2f\t",a[j][i]);
printf("\n");
}
//прямой ход
for( k = 0; k < n; k++ )
{
j_max = k;
for( j = k; j < n; j++)
if ( fabs(a[j_max][k] ) < fabs (a[j][k]) )
j_max = j;
//переставляем строки
for(i = 0; i < n + 1; i++)
{
t = a[k][i];
a[k][i] = a[j_max][i];
a[j_max][i] = t;
}
//вывод полученной матрицы
printf("матрица после %d преобразований\n",k+1);
for(j = 0; j < n; j++)
{
for(i = 0; i < n + 1; i++)
printf("%6.2f\t",a[j][i]);
printf("\n");
}
//если максимальный элемент нулевой
if(a[j_max][k] == 0)
{
count = 0;
for(i = 0; i < n; i++)
{
if(a[k][i] == 0)
count++;
printf("кол-во нулей: %d\n",count);
if(count == n && a[k][n + 1] == 0)//если коэфф. в строке = 0 и своб. член = 0
{
printf("СЛАУ имеет множество решений\n");
return(0);
}
else if (count == n && a[k][n + 1] != 0)//если коэфф. в строке = 0 и своб. член не равен 0
{
printf("СЛАУ не имеет решений\n");
return(0);
}
}
}
//выполнение вычислений
for(j = n; j >= k; j--)
a[k][j] = a[k][j]/a[k][k];//делим на коэффиц. a[1][1],a[2][2] и т.д.
for(i = k + 1; i < n; i++)
for(j = n; j >= k; j--)
a[i][j] = a[i][j] - a[i][k]*a[k][j];//вычитаем из 2 ур-ия 1-ое умнож. на коэфф. и т.д. */
}
//вывод матрицы треугольного вида
printf("Матрица приведенная к треугольному виду:\n");
for(j = 0; j < n; j++)
{
for(i = 0; i < n + 1; i++)
printf("%6.2f\t",a[j][i]);
printf("\n");
}
//обратный ход
for(i = 0; i < n; i++)
x[i] = a[i][n];
for(i = n-2; i >= 0; i--)
for(j = i+1; j < n; j++)
x[i] = x[i] - x[j]*a[i][j];//находим корни
//вывод решения
printf("Корни СЛАУ:\n");
for(i = 0; i < n; i++)
printf("x[%d] = %6.2f\n",i,x[i]);
}
Объяснение кода листинга программы
В коде представлена реализация решения системы линейных уравнений методом Гаусса с выбором главного элемента по столбцу.
- Ввод размерности матрицы:
В этой части кода пользователь вводит размерность матрицы, которая представляет собой количество уравнений в системе. Введенное значение сохраняется в переменной
n. - Ввод СЛАУ:
Здесь пользователю предлагается ввести СЛАУ, то есть исходные данные системы линейных уравнений. Код просит ввести все элементы матрицы
a[j][i]и сохраняет их в соответствующих переменных. - Прямой ход:
Этот блок кода представляет собой прямой ход метода Гаусса. Он начинается с инициализации переменной
kравной 0 и продолжается до тех пор, покаkменьшеn. В каждой итерации код находит максимальное значение в текущем столбце матрицы и переставляет строки так, чтобы главный элемент был на позицииk. Затем код выполняет соответствующие вычисления для преобразования матрицы. - Матрица приведенная к треугольному виду:
Здесь выводится матрица
a[j][i], преобразованная в треугольный вид. - Обратный ход:
Этот блок кода представляет собой обратный ход метода Гаусса. Он начинается с инициализации всех переменных
x[i]равнымиa[i][n]. Затем, двигаясь отn-1к 0, для каждогоiвычисляется значениеx[i]как остаток от деленияa[i][j]наa[j][j]. - Вывод решения:
В этой части кода выводятся значения корней системы
x[i]на экран. Код не содержит ошибок и должен корректно работать для любой размерности матрицы и СЛАУ.