#c #matrix #partial #gaussian #determinants
#c #матрица #частичный #гауссовский #определители
Вопрос:
Я пытаюсь создать простое консольное приложение на C, которое будет вычислять определитель матрицы, используя метод исключения частичного поворота Gauss. 2 проблемы, которые у меня есть: — Кто-то сказал мне, что есть определенные матрицы, которые не работают с этим методом (с математической точки зрения), после прочтения статей в Google я не смог найти, что это за особый случай — после множества тестов я обнаружил, что моя программа не работает для некоторых матриц, после 2 дней «пустой траты» времени на редактирование и отмену я не смог найти проблему.
Любой тип улучшений более чем приветствуется. Я только начинаю с C.
#include<stdio.h>
#include<cstdlib>
#include<math.h>
#include<conio.h>
#include<windows.h>
// calculate biggest element on column
int indice_max(int dim, int col, float coloana[20][20]) {
float max = 0;
int indice;
for(int i = 1; i <= dim; i )
if(fabs(max) < fabs(coloana[i][col])) {
max = coloana[i][col];
indice = i;
}
return indice;
}
// permute 2 lines
void permutare_linie(int linie1, int linie2, int dim, float matrice[20][20]) {
float aux;
for(int i = 1; i <= dim; i ) {
aux = matrice[linie1][i];
matrice[linie1][i] = matrice[linie2][i];
matrice[linie2][i] = aux;
}
}
// print matrix
void afisare_matrice(int dimensiune, float matrice[20][20], int lpiv) {
for(int i = 1; i<= dimensiune; i ) {
for(int j = 1; j <= dimensiune; j ) {
if(i == lpiv)
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_GREEN);
else
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE );
printf("%4.2f ", matrice[i][j]);
}
printf("n");
}
}
void main(void) {
float matrice[20][20];
int dimensiune ;
float rezultat = 1;
float pivot;
int lpiv;
int cpiv;
int optiune;
while(1) {
// MENU
printf("ALEGET OPTIUNEA:n");
printf("1) Calculate matrix determinantn");
printf("2) Exitn");
scanf("%d", amp;optiune);
if(optiune == 1) {
// Read determinant dimension
printf("Matrix dimension:");
scanf("%d", amp;dimensiune);
// Read determinant
for(int i = 1; i <= dimensiune; i )
for(int j = 1; j <= dimensiune; j ) {
printf("M[%d][%d]=", i, j);
scanf("%f", amp;matrice[i][j]);
}
// pivot initial coords
lpiv = 1;
cpiv = 1;
printf("n----- Entered Matrix -----nn");
afisare_matrice(dimensiune, matrice, 0);
printf("n");
for(int pas = 1; pas <= dimensiune - 1; pas ) {
if(fabs(matrice[lpiv][cpiv]) > fabs(matrice[indice_max(dimensiune, cpiv, matrice)][cpiv])) {
permutare_linie(lpiv, indice_max(dimensiune, cpiv, matrice), dimensiune, matrice);
rezultat = -(rezultat);
}
pivot = matrice[lpiv][cpiv];
for(int inm = 1; inm <= dimensiune; inm ) {
matrice[lpiv][inm] = matrice[lpiv][inm] / pivot;
}
rezultat *= fabs(pivot);
// transform matrix to a superior triangular
for(int l = lpiv 1; l <= dimensiune; l )
for(int c=cpiv 1; c <= dimensiune; c ) {
matrice[l][c] -= matrice[l][cpiv] * matrice[lpiv][c] / matrice[lpiv][cpiv];
}
for(int i = lpiv 1; i <= dimensiune; i )
matrice[i][cpiv] = 0;
// afisam rezultat / pas
printf("----- Step %d -----nn", pas);
afisare_matrice(dimensiune, matrice, lpiv);
printf("nResult after step %d : %4.2fnn", pas, rezultat);
lpiv ;
cpiv ;
}
// final result
rezultat = rezultat * matrice[dimensiune][dimensiune];
printf("----- REZULTAT FINAL -----nn");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
printf("Rezultat = %4.2fnRezultat rotunjit:%4.0fnn", rezultat, floorf(rezultat * 100 0.5) / 100);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE );
}
else {
exit(0);
}
}
}
Комментарии:
1. что ж, зайдите в библиотеку и найдите книгу по численным методам, таким как Численные методы, Burden amp; Faires, если я не ошибаюсь, и посмотрите их реализацию на C для устранения Гаусса, HTH
2. Это объясняется в записи в Википедии «Квадратная матрица, которая не является обратимой, называется сингулярной или вырожденной. Квадратная матрица является сингулярной тогда и только тогда, когда ее определитель равен 0. Сингулярные матрицы редки в том смысле, что если вы выберете случайную квадратную матрицу, она почти наверняка не будет сингулярной. »
3. Не нужно даже идти в библиотеку! Ознакомьтесь с главой 2: nrbook.com/a/bookcpdf.php
4. @user786653 В вашем объяснении говорится, когда матрица не обратима. Сингулярная матрица — это когда ее определитель равен 0, но мне нужно вычислить определитель, чтобы увидеть, равно ли оно 0 или нет. В Интернете есть примеры кода для этой процедуры, но они не выполняют те же шаги, что делает мой университетский профессор.
5. Смотрите ответ @anatolygs, в какой-то момент сингулярная матрица будет иметь нулевой столбец, нет необходимости явно вычислять определитель.
Ответ №1:
Ваш код выполняет некоторое разделение:
matrice[lpiv][inm] = matrice[lpiv][inm] / pivot;
Если произойдет деление на ноль, возникнет ошибка. Я думаю, это произойдет для нулевой матрицы.
Похоже, что ваш код на самом деле пытается инвертировать матрицу, а не просто вычислять определитель.
Комментарии:
1. Конечно, я думал, что один из элементов по диагонали равен 0, но не думал, что они могут быть равны 0 после операций, выполненных для преобразования матрицы в превосходную треугольную. Спасибо. Я думаю, что нашел и другую проблему. Я ищу максимальный элемент во всем столбце, а не только под сводом.