Baixe o app para aproveitar ainda mais
Esta é uma pré-visualização de arquivo. Entre para ver o arquivo original
Leia-me - Como carregar uma matriz por arquivo.txt Para escrever sistema linear em um arquivo de formato .txt basta digitar os coeficientes da matriz do sistema. Siga o exemplo: Você tem o seguinte sistema linear: 2 x1 + 5 x2 + 3 x3 = 19 1 x1 + 4 x2 + 2 x3 = 15 7 x1 + 1 x2 + 6 x3 = 27 Seu arquivo .txt deve ter a seguinte informação (somente os coeficientes): 2 5 3 19 1 4 2 15 7 1 6 27 Determinante e Inversa.c //Calculo do determinante e da inversa de uma matriz quadrada qualquer //Luiz Vinicius Soglia - lvmsoglia@hotmail.com #include <stdio.h> #include <math.h> #include <stdlib.h> #include <string.h> //========================================================================================================== // Função para calcular o Determinante e a Inversa de uma matriz //n é a ordem da matriz que se deseja calcular o determinante e a inversa //mA é a matriz que se deseja calcular //mI é uma matriz que guardará a matriz inversa ao final da execução da função, caso exista inversa (det diferente de zero) float det_inversa (int n, float mA[][n], float mI[][n]) { int i, j, k, posl, erro; float det, aux, pivo, m; //Constroi a matriz identidade [mI] para ser usada no calculo da inversa for (i=0; i<n; i++) { for (j=0; j<n; j++) { if (i==j) {mI[i][j] = 1.0;} //diagonal principal else {mI[i][j] = 0.0;} } } det=1.0; //det inicialmente guarda as trocas de sinal do determinante, caso haja mudanças de linhas no pivoteamento parcial erro = 0; //A variavel erro se tornara 1 caso haja erros de divisao por zero //pivoteamento parcial e Metodo da eliminacao de Gauss (Triangularizacao superior) for (k=0; k<(n-1); k++) { pivo=fabs(mA[k][k]); //pivo inicial posl=k; //posicao da linha do pivo for (i=k+1; i<n; i++) { if (fabs(mA[i][k])>pivo) { pivo=fabs(mA[i][k]); //passa a ser o novo pivo posl=i; //guardam a posicao (linha e coluna) do maior pivo } } if (posl!=k) //caso o pivo nao esteja na linha k, troca linha k pela linha posl { for (j=k; j<n; j++) { aux=mA[k][j]; mA[k][j]=mA[posl][j]; mA[posl][j]=aux; } //tambem faz as mesmas operacoes na matriz identidade for (j=0; j<n; j++) { aux=mI[k][j]; mI[k][j]=mI[posl][j]; mI[posl][j]=aux; } if ((posl-k)%2 != 0) //se for um numero impar de diferença entre as linhas {det = det*(-1);} //com a troca de linhas, o determinante muda de sinal, det guarda o sinal do determinante } //Metodo da eliminacao de Gauss (Triangularizacao superior) if (mA[k][k] != 0) //Evita erros de divisao por zero { for (i=k+1; i<n; i++) { m = mA[i][k]/mA[k][k]; //calcula o multiplicador mA[i][k] = 0.0; //agora assume zero para o valor a ser zerado, afim de poupar tempo for (j=k+1; j<n; j++) //comeca do elemento apos o valor a ser zerado { mA[i][j] = mA[i][j] - (m*mA[k][j]); } //tambem faz as mesmas operacoes na matriz identidade for (j=0; j<n; j++) { mI[i][j] = mI[i][j] - (m*mI[k][j]); } } } else {erro = 1; break;} //Houve erro de divisão por zero - todos os pivôs são zero } //fim do pivoteamento parcial e Metodo da eliminacao de Gauss (Triangularizacao superior) if (erro == 1) //Houve erro de divisao por zero - um dos pivos é igual a zero e com isso det sera zero {return 0.0;} //Calcula o det. Como a matriz agora eh triangular superior, o det sera o produto dos elementos da diagonal principal for (k=0; k<n; k++) {det = det * mA[k][k];} if (det == 0.0) {return 0.0;} //calcula a inversa - faz uma triangularizacao inferior para tornar a matriz [mA] uma matriz diagonal e depois identidade //mas esses passos só serão aplicados em [mI], que guardara a matriz inversa ao final dos passos for (k=n-1; k>0; k--) { if (mA[k][k] != 0) //Evita erros de divisao por zero { for (i=k-1; i>=0; i--) { m = mA[i][k]/mA[k][k]; //calcula o multiplicador for (j=0; j<n; j++) { mI[i][j] = mI[i][j] - (m*mI[k][j]); } } } else {erro = 1; break;} //Houve erro de divisão por zero - um elemento da diagonal principal eh igual a zero } if (erro == 1) {return 0.0;} //finaliza dividindo a matriz [pelos elementos da diagonal principal, ultimo passo para transforma-la em matriz inversa for (i=0; i<n; i++) { for (j=0; j<n; j++) { mI[i][j] = mI[i][j]/mA[i][i]; } } return det; } //========================================================================================================== //Função principal int main() { int n, i, j, carregamento; char op, nome_arq[260]; float det; FILE *fp; do { printf ("Calculo do Determinate e da Inversa de uma matriz quadrada [A] qualquer\n\n"); do { printf ("Digite a ordem da matriz quadrada (n), no maximo n=100: "); fflush(stdin); scanf ("%d",&n); } while (n < 2 || n > 100); printf ("\nDigite a opcao para o carregamento do sistema linear:\n\n[1] Digitar os dados aqui\n[2] Atraves de um arquivo .txt\n\n"); do { printf ("Opcao: "); fflush(stdin); scanf ("%d",&carregamento); } while (carregamento < 1 || carregamento > 2); //Cria as matrizes float mA[n][n], mI[n][n]; //cria a matriz [mA] e uma matriz que guardara a sua inversa [mI] //faz o carregamento da matriz [mA] de acordo com a opcao escolhida switch (carregamento) { case 1: //digita a matriz for (i=0; i<n; i++) { do { system ("cls"); printf ("Digite os elementos da linha %d:\n\n", i+1); for (j=0; j<n; j++) { printf ("a[%d][%d] = ", i+1, j+1); scanf ("%f", &mA[i][j]); } printf ("\nOs valores digitados estao corretos? (digite [S] para sim, ou [N] para nao): "); fflush(stdin); op = getchar(); } while (op != 's' && op != 'S'); } break; case 2: //carrega do arquivo do { printf ("\nDigite o caminho (com a extensao) do arquivo de texto com os dados:\n"); fflush(stdin); scanf ("%259[^\n]",nome_arq); fp=fopen(nome_arq,"r"); if (!fp) { printf ("\nErro na abertura do arquivo! Pressione [ENTER] para continuar\n"); fflush(stdin); op = getchar(); } } while(!fp); //inicializa e lê os coeficientes da matriz mA for (i=0; i<n; i++) { for (j=0; j<n; j++) { mA[i][j]=0.0; fscanf (fp, "%f", &mA[i][j]); } } fclose(fp); break; default: printf ("\nOcorreu um erro! Pressione [ENTER] para sair\n"); fflush(stdin); op = getchar(); return 0; } //fim do carregamento da matriz system ("cls"); printf ("Dados carregados com sucesso!\nPressione [ENTER] para continuar e calcular o Determinante e a Inversa\n"); fflush(stdin); op = getchar(); system ("cls"); //Chama a funcao que calcula o determinante e a inversa da matriz det = det_inversa (n, mA, mI); if (det == 0.0) //se det igual a zero a matriz nao possui inversa {printf ("Determinante (det A) = 0\nA matriz A nao possui inversa!\n\nPressione [ENTER] para sair\n"); op = getchar(); return 0;} printf ("Determinante (det A) = %f\n\nDeseja visualizar a Inversa da matriz? Digite [S] para sim, ou [N] para nao: ", det); fflush(stdin); op = getchar(); fflush(stdin); if (op == 's' || op == 'S') { //cria o arquivo de texto .txt para escrita if ((fp = fopen ("MATRIZ_INVERSA.txt", "w")) == NULL) {printf ("\nErro ao salvar a matriz inversa em um arquivo!\n\nPressione [ENTER] para sair!\n"); op = getchar(); return 0;} //imprime a matriz inversa no arquivo de texto .txt for (i=0; i<n; i++) { for (j=0; j<n; j++) { fprintf (fp, "%f ", mI[i][j]); } fprintf (fp, "\n"); } fclose (fp); //abre o arquivo com o resultado para o usuario visualizar system ("start MATRIZ_INVERSA.txt"); } printf ("\nDeseja reiniciar o programa? (digite [S] para sim, ou [N] para nao): "); fflush(stdin); op = getchar(); system ("cls"); } while (op == 's' || op == 'S'); return 0; } Eliminacao de Gauss.c //Resolucao de sistemas lineares utilizando o metodo da eliminacao de Gauss //Luiz Vinicius Soglia - lvmsoglia@hotmail.com #include <stdio.h> #include <math.h> #include <stdlib.h> #include <string.h> //========================================================================================================== //troca na str o caractere ca pelo caractere cb void troca_caractere (char *str, const char ca, const char cb) { int n, i; n = strlen(str); for (i=0; i<n; i++) { if (str[i] == ca) {str[i] = cb;} } } //========================================================================================================== //funcao que implementa a resolução de sistemas lineares pela eliminação de Gauss e retrossubstituição. //n: é a ordem do sistema. //metodo: guarda o método a ser utilizado para a resulução: 1 = sem pivoteamento, 2 = pivoteamento parcial, 3 = pivoteamento total. //matriz a[][]: é a matriz dos coeficientes. //matriz b[]: é a matriz dos termos independentes. //matriz x[]: guarda os valores das variaveis após a resolução. //matriz o[] guarda a coluna correspondente a cada variavel, pois no pivoetamento total pode ocorrer troca de colunas. //retorna 0 caso haja sucesso, 1 para erros de entrada de argumentos invalidos, e 2 para erros de divisão por zero. int eliminacao_gauss (int n, int metodo, float a[][n], float b[], float x[], int o[]) { int k, i, j, posl, posc, erro; float m, soma, aux, pivo; if (n<2) {return 1;} //a ordem do sistema tem que ser maior ou igual a 2 for (i=0; i<n; i++) //inicializa as variaveis x (por precaução) e o vetor ordem das variaveis x {x[i]=0; o[i]=i+1;} erro = 0; //A variavel erro se tornara 1 caso haja erros de divisao por zero switch (metodo) //triangulariza a matriz do sistema linerar de acordo com o metodo escolhido { //sem pivoteamento ===================================================== case 1: for (k=0; k<(n-1); k++) { //Metodo da eliminacao de Gauss (Triangularizacao) if (a[k][k] != 0.0) //Evita erros de divisao por zero { for (i=k+1; i<n; i++) { m = a[i][k]/a[k][k]; //calcula o multiplicador a[i][k] = 0.0; //agora assume zero para o valor a ser zerado, afim de poupar tempo for (j=k+1; j<n; j++) //comeca do elemento apos o valor a ser zerado { a[i][j] = a[i][j] - (m*a[k][j]); } b[i] = b[i] - m*b[k]; } } else {erro = 1; break;} //Houve erro de divisão por zero } break; //pivoteamento parcial ================================================= case 2: for (k=0; k<(n-1); k++) { pivo=fabs(a[k][k]); //pivo inicial posl=k; //posicao da linha do pivo for (i=k+1; i<n; i++) { if (fabs(a[i][k])>pivo) { pivo=fabs(a[i][k]); //passa a ser o novo pivo posl=i; //guarda a posicao da linha do maior pivo } } if (posl!=k) //caso o pivo nao esteja na linha k, troca linha k pela linha posl { for (j=k; j<n; j++) //comeca a troca dos elementos apos os elementos zerados { aux=a[k][j]; a[k][j]=a[posl][j]; a[posl][j]=aux; } aux=b[k]; b[k]=b[posl]; b[posl]=aux; } //Metodo da eliminacao de Gauss (Triangularizacao) if (a[k][k] != 0.0) //Evita erros de divisao por zero, caso o pivo seja zero { for (i=k+1; i<n; i++) { m = a[i][k]/a[k][k]; //calcula o multiplicador a[i][k] = 0.0; //agora assume zero para o valor a ser zerado, afim de poupar tempo for (j=k+1; j<n; j++) //comeca do elemento apos o valor a ser zerado { a[i][j] = a[i][j] - (m*a[k][j]); } b[i] = b[i] - m*b[k]; } } else {erro = 1; break;} //Houve erro de divisão por zero } break; //pivoteamento total =================================================== case 3: for (k=0; k<(n-1); k++) { pivo=fabs(a[k][k]); //pivo inicial posl=k; //posicao da linha do pivo posc=k;//posicao da coluna do pivo for (i=k; i<n; i++) { for (j=k; j<n; j++) { if (fabs(a[i][j])>pivo) { pivo=fabs(a[i][j]); //passa a ser o novo pivo //guardam a posicao (linha e coluna) do maior pivo posl=i; posc=j; } } } if (posl!=k) //caso o pivo nao esteja na linha k, troca linha k pela linha posl { for (j=k; j<n; j++) //comeca a troca dos elementos apos os elementos zerados { aux=a[k][j]; a[k][j]=a[posl][j]; a[posl][j]=aux; } aux=b[k]; b[k]=b[posl]; b[posl]=aux; } if (posc!=k) //caso o pivo nao esteja na coluna k, troca coluna k pela coluna posc { for (j=0; j<n; j++) { aux=a[j][k]; a[j][k]=a[j][posc]; a[j][posc]=aux; } //como houve troca de coluna, atualiza o vetor que guarda a ordem das incognitas x aux=o[k]; o[k]=o[posc]; o[posc]=aux; } //Metodo da eliminacao de Gauss (Triangularizacao) if (a[k][k] != 0.0) //Evita erros de divisao por zero { for (i=k+1; i<n; i++) { m = a[i][k]/a[k][k]; //calcula o multiplicador a[i][k] = 0.0; //agora assume zero para o valor a ser zerado, afim de poupar tempo for (j=k+1; j<n; j++) //comeca do elemento apos o valor a ser zerado { a[i][j] = a[i][j] - (m*a[k][j]); } b[i] = b[i] - m*b[k]; } } else {erro = 1; break;} //Houve erro de divisão por zero } break; //Caso não exista a opção de método passada para a função, implica em erro. Retorna 1, indicando esse erro. default: return 1; } //fim do switch-case com os metodos de triangularizacao if (erro == 1) //Houve erro de divisão por zero. Retorna 2, indicando esse erro. {return 2;} //Caso não haja erros na eliminação de Gauss, aplica o Metodo de resolucao de sistemas triangulares (Retrosubstituicao) if (a[n-1][n-1] != 0.0) {x[n-1] = b[n-1] / a[n-1][n-1];} else {return 2;} //antes atribuia zero a variavel: {x[n-1] = 0.0;}, mas achei melhor retornar o erro como uma divisão por zero for (i=n-2; i>-1; i--) { soma = 0.0; for (j=i+1; j<n; j++) {soma = soma + a[i][j]*x[j];} if (a[i][i] != 0) {x[i] = (b[i] - soma)/a[i][i];} else {return 2;} //antes atribuia zero a variavel: {x[i] = 0.0;}, mas achei melhor retornar o erro como uma divisão por zero } return 0; } //========================================================================================================== //Função principal int main() { int n, i, j, metodo, carregamento, teste; char op, nome_arq[260], buffer[64]; FILE *fp; do { printf ("Resolucao de sistemas lineares utilizando o metodo da eliminacao de Gauss\n\n"); do { printf ("Digite a ordem do sistema (n), no maximo n=100: "); fflush(stdin); scanf ("%d",&n); } while (n < 2 || n > 100); printf ("\nDigite a opcao do metodo de pivoteamento:\n\n[1] Sem pivoteamento\n[2] Pivoteamento parcial\n[3] Pivoteamento total\n\n"); do { printf ("Opcao: "); fflush(stdin); scanf ("%d",&metodo); } while (metodo < 1 || metodo > 3); printf ("\nDigite a opcao para o carregamento do sistema linear:\n\n[1] Digitar os dados aqui\n[2] Atraves de um arquivo .txt\n\n"); do { printf ("Opcao: "); fflush(stdin); scanf ("%d",&carregamento); } while (carregamento < 1 || carregamento > 2); //Cria as matrizes float a[n][n], x[n], b[n]; //cria as matrizes dos coeficientes (A), das variaveis (X) e dos termos independentes (B) int o[n]; //vetor que guarda a ordem das incognitas x //faz o carregamento da matriz do sistema de acordo com a opcao escolhida switch (carregamento) { case 1: //digita a matriz for (i=0; i<n; i++) { do { system ("cls"); printf ("Digite os elementos da linha %d:\n\n", i+1); for (j=0; j<n; j++) { printf ("a[%d][%d] = ", i+1, j+1); scanf ("%f", &a[i][j]); } printf ("\nb[%d] = ", i+1); scanf ("%f", &b[i]); printf ("\nOs valores digitados estao corretos? (digite [S] para sim, ou [N] para nao): "); fflush(stdin); op = getchar(); } while (op != 's' && op != 'S'); } break; case 2: //carrega do arquivo do { printf ("\nDigite o caminho do arquivo de texto (com a extensao) que contem os dados:\n"); fflush(stdin); scanf ("%259[^\n]",nome_arq); fp=fopen(nome_arq,"r"); if (!fp) { printf ("\nErro na abertura do arquivo! Pressione [ENTER] para continuar\n"); fflush(stdin); op = getchar(); } } while(!fp); //inicializa e lê os coeficientes das matrizes A e B for (i=0; i<n; i++) { for (j=0; j<n; j++) { a[i][j]=0.0; fscanf (fp, "%f", &a[i][j]); } b[i]=0.0; fscanf (fp, "%f", &b[i]); } fclose(fp); break; default: printf ("\nOcorreu um erro no carregamento do sistema! Pressione [ENTER] para sair\n"); fflush(stdin); op = getchar(); return 0; } //fim do carregamento da matriz system ("cls"); printf ("Dados carregados! Pressione [ENTER] para continuar e resolver o sistema linear\n"); fflush(stdin); op = getchar(); system ("cls"); //Chama a função que aplica o metodo da eliminação de Gauss e a retrosubstituição teste = eliminacao_gauss (n, metodo, a, b, x, o); //retorna zero para teste caso haja sucesso if (teste == 1) ///se a função retornar 1, argumentos invalidos foram passados para a função { printf ("Erro! Argumentos invalidos foram digitados!\n\nPressione [ENTER] para sair\n"); fflush(stdin); op = getchar(); return 0; } if (teste == 2) //se a função retornar 2 houve erro de divisão por zero durante o calculo { printf ("Erro! Ocorreu uma divisao por zero! Talvez nao haja solucao!\n\nPressione [ENTER] para sair\n"); fflush(stdin); op = getchar(); return 0; } //exibe o resultado na tela printf ("Resultados:\n\n"); for (i=0; i<n; i++) {printf ("x%d = %f\n", o[i], x[i]);} printf ("\nDeseja salvar os resultados para um arquivo .csv?\nDigite [S] para sim, ou [N] para nao: "); fflush(stdin); op = getchar(); fflush(stdin); if (op == 's' || op == 'S') //salva os resultados em um arquivo .csv { printf ("\nDigite o nome do arquivo onde os resultados serao salvos:\n"); scanf("%255[^\n]", nome_arq); fflush (stdin); strcat (nome_arq, ".csv"); //adiciona a extensao .csv no nome do arquivo troca_caractere (nome_arq, ' ', '_'); //substitui ' ' por '_' no nome do arquivo para evitar erros na abertura pela funcao system() //cria o arquivo de texto .csv para escrita if ((fp = fopen (nome_arq, "w")) == NULL) {printf ("\nErro na criacao do arquivo\n\nPressione [ENTER] para sair!\n"); op = getchar(); return 0;} //imprime um cabecalho no arquivo de texto .csv - sep=; indica que o separador de colunas eh um ; fprintf(fp, "sep=;\n"); for (i=0; i<(n-1); i++) {fprintf (fp, "x%d;", o[i]);} fprintf (fp, "x%d\n", o[n-1]); //imprime a matriz no arquivo de texto .csv for (i=0; i<n; i++) { for (j=0; j<n; j++) { snprintf (buffer, 266, "%f", a[i][j]); troca_caractere (buffer, '.', ','); //troca o separador decimal de ponto para virgula, que eh o padrao do Brasil fprintf (fp, "%s;", buffer); } snprintf (buffer, 266, "%f", b[i]); troca_caractere (buffer, '.', ','); //troca o separador decimal de ponto para virgula, que eh o padrao do Brasil fprintf (fp, "=;%s\n", buffer); } //imprime os resultados das variaveis for (i=0; i<n; i++) { snprintf (buffer, 266, "x%d =;%f", o[i], x[i]); troca_caractere (buffer, '.', ','); //troca o separador decimal de ponto para virgula, que eh o padrao do Brasil fprintf (fp, "\n%s", buffer); } fclose (fp); //abre o arquivo com o resultado para o usuario visualizar strcpy (buffer, "start "); strcat (buffer, nome_arq); system (buffer); } //fim do procedimento para salvar o resultado em um arquivo .csv printf ("\nDeseja reiniciar o programa? (digite [S] para sim, ou [N] para nao): "); fflush(stdin); op = getchar(); system ("cls"); } while (op == 's' || op == 'S'); return 0; } Fatoracao LU.c //Resolucao de sistemas lineares utilizando o metodo da fatoracao LU com pivoteamento parcial //Luiz Vinicius Soglia - lvmsoglia@hotmail.com #include <stdio.h> #include <math.h> #include <stdlib.h> #include <string.h> //========================================================================================================== //troca na str o caractere ca pelo caractere cb void troca_caractere (char *str, const char ca, const char cb) { int n, i; n = strlen(str); for (i=0; i<n; i++) { if (str[i] == ca) {str[i] = cb;} } } //========================================================================================================== //funcao que implementa a resolução de sistemas lineares pela fatoracao LU com pivoteamento parcial //n: é a ordem do sistema. //matriz a[][]: //é a matriz dos coeficientes. Ao final do metodo ela guardara a matriz LU, com L abaixo da diagonal principal e U nas outras posicoes. //matriz b[]: é a matriz dos termos independentes. //matriz x[]: guarda os valores das variaveis após a resolução. //retorna 0 caso haja sucesso, 1 para erros de entrada de argumentos invalidos, e 2 para erros de divisão por zero. int fatoracao_LU (int n, float a[][n], float b[], float x[]) { int k, i, j, posl, erro; float m, soma, aux, pivo, y[n]; if (n<2) {return 1;} //a ordem do sistema tem que ser maior ou igual a 2 for (i=0; i<n; i++) //inicializa as variaveis x (por precaução) {x[i]=0;} erro=0; //A variavel erro se tornara 1 caso haja erros de divisao por zero //pivoteamento parcial for (k=0; k<(n-1); k++) { pivo=fabs(a[k][k]); //pivo inicial posl=k; //posicao da linha do pivo for (i=k+1; i<n; i++) { if (fabs(a[i][k])>pivo) { pivo=fabs(a[i][k]); //passa a ser o novo pivo posl=i; //guarda a posicao da linha do maior pivo } } if (posl!=k) //caso o pivo nao esteja na linha k, troca linha k pela linha posl { for (j=0; j<n; j++)//permuta as linhas da matriz a[][] { aux=a[k][j]; a[k][j]=a[posl][j]; a[posl][j]=aux; } aux=b[k]; //tambem permuta as linhas da matriz b[] b[k]=b[posl]; b[posl]=aux; } //Triangularizacao da matriz a[][], para a obtenção da matriz LU if (a[k][k] != 0.0) //Evita erros de divisao por zero, caso o pivo seja zero { for (i=k+1; i<n; i++) { m = a[i][k]/a[k][k]; //calcula o multiplicador //guarda os multiplicadores nas posicoes que deveriam ser zeradas. //Assim a matriz a[][] guarda L abaixo da diagonal principal e guarda U no restante das posicoes. Isso economiza memoria a[i][k] = m; for (j=k+1; j<n; j++) //comeca do elemento apos o valor a ser zerado (que na verdade esta guardando os multiplicadores) { a[i][j] = a[i][j] - (m*a[k][j]); } } } else {erro = 1; break;} //Houve erro de divisão por zero } if (erro == 1) //Houve erro de divisão por zero. Retorna 2, indicando esse erro. {return 2;} //Resolve o sistema L Y = B, obtendo Y k=0; for (i=0; i<n; i++) { soma=0.0; for (j=0; j<i; j++) { soma = soma + y[j]*a[i][j]; //a[i][j] neste caso guarda os multiplicadores m (os termos abaixo da diagonal principal da matriz L) } y[k] = b[i] - soma; k++; } //Resolve o sistema U X = Y, obtendo X, utilizando o metodo da resolucao de um sistema triangular superior if (a[n-1][n-1] != 0.0) {x[n-1] = y[n-1] / a[n-1][n-1];} else {return 2;} //erro de divisão por zero for (i=n-2; i>-1; i--) { soma = 0.0; for (j=i+1; j<n; j++) {soma = soma + a[i][j]*x[j];} if (a[i][i] != 0) {x[i] = (y[i] - soma)/a[i][i];} else {return 2;} //erro de divisão por zero } return 0; } //========================================================================================================== //Função principal int main() { int n, i, j, carregamento, teste; char op, nome_arq[260], buffer[64]; FILE *fp; do { printf ("Resolucao de sistemas lineares utilizando fatoracao LU com pivoteamento parcial\n\n"); do { printf ("Digite a ordem do sistema (n), no maximo n=100: "); fflush(stdin); scanf ("%d",&n); } while (n < 2 || n > 100); printf ("\nDigite a opcao para o carregamento do sistema linear:\n\n[1] Digitar os dados aqui\n[2] Atraves de um arquivo .txt\n\n"); do { printf ("Opcao: "); fflush(stdin); scanf ("%d",&carregamento); } while (carregamento < 1 || carregamento > 2); //Cria as matrizes float a[n][n], x[n], b[n]; //cria as matrizes dos coeficientes (A), das variaveis (X) e dos termos independentes (B) //faz o carregamento da matriz do sistema de acordo com a opcao escolhida switch (carregamento) { case 1: //digita a matriz for (i=0; i<n; i++) { do { system ("cls"); printf ("Digite os elementos da linha %d:\n\n", i+1); for (j=0; j<n; j++) { printf ("a[%d][%d] = ", i+1, j+1); scanf ("%f", &a[i][j]); } printf ("\nb[%d] = ", i+1); scanf ("%f", &b[i]); printf ("\nOs valores digitados estao corretos? (digite [S] para sim, ou [N] para nao): "); fflush(stdin); op = getchar(); } while (op != 's' && op != 'S'); } break; case 2: //carrega do arquivo do { printf ("\nDigite o caminho do arquivo de texto (com a extensao) que contem os dados:\n"); fflush(stdin); scanf ("%259[^\n]",nome_arq); fp=fopen(nome_arq,"r"); if (!fp) { printf ("\nErro na abertura do arquivo! Pressione [ENTER] para continuar\n"); fflush(stdin); op = getchar(); } } while(!fp); //inicializa e lê os coeficientes das matrizes A e B for (i=0; i<n; i++) { for (j=0; j<n; j++) { a[i][j]=0.0; fscanf (fp, "%f", &a[i][j]); } b[i]=0.0; fscanf (fp, "%f", &b[i]); } fclose(fp); break; default: printf ("\nOcorreu um erro no carregamento do sistema! Pressione [ENTER] para sair\n"); fflush(stdin); op = getchar(); return 0; } //fim do carregamento da matriz system ("cls"); printf ("Dados carregados! Pressione [ENTER] para continuar e resolver o sistema linear\n"); fflush(stdin); op = getchar(); system ("cls"); //Chama a função que aplica o metodo da fatorcao LU teste = fatoracao_LU (n, a, b, x); //retorna zero para teste caso haja sucesso if (teste == 1) ///se a função retornar 1, argumentos invalidos foram passados para a função { printf ("Erro! Argumentos invalidos foram digitados!\n\nPressione [ENTER] para sair\n"); fflush(stdin); op = getchar(); return 0; } if (teste == 2) //se a função retornar 2 houve erro de divisão por zero durante o calculo { printf ("Erro! Ocorreu uma divisao por zero! Talvez nao haja solucao!\n\nPressione [ENTER] para sair\n"); fflush(stdin); op = getchar(); return 0; } //exibe o resultado na tela printf ("Resultados:\n\n"); for (i=0; i<n; i++) {printf ("x%d = %f\n", i+1, x[i]);} printf ("\nDeseja salvar os resultados para um arquivo .csv?\nDigite [S] para sim, ou [N] para nao: "); fflush(stdin); op = getchar(); fflush(stdin); if (op == 's' || op == 'S') //salva os resultados em um arquivo .csv { printf ("\nDigite o nome do arquivo onde os resultados serao salvos:\n"); scanf("%255[^\n]", nome_arq); fflush (stdin); strcat (nome_arq, ".csv"); //adiciona a extensao .csv no nome do arquivo troca_caractere (nome_arq, ' ', '_'); //substitui ' ' por '_' no nome do arquivo para evitar erros na abertura pela funcao system() //cria o arquivo de texto .csv para escrita if ((fp = fopen (nome_arq, "w")) == NULL) {printf ("\nErro na criacao do arquivo\n\nPressione [ENTER] para sair!\n"); op = getchar(); return 0;} //imprime um cabecalho no arquivo de texto .csv - sep=; indica que o separador de colunas eh um ; fprintf(fp, "sep=;\nMatriz LU - L abaixo da diagonal principal e U nas outras posicoes\n\n"); for (i=0; i<(n-1); i++) {fprintf (fp, "x%d;", i+1);} fprintf (fp, "x%d;;Pb\n", n); //imprime a matriz no arquivo de texto .csv for (i=0; i<n; i++) { for (j=0; j<n; j++) { snprintf (buffer, 266, "%f", a[i][j]); troca_caractere (buffer, '.', ','); //troca o separador decimal de ponto para virgula, que eh o padrao do Brasil fprintf (fp, "%s;", buffer); } snprintf (buffer, 266, "%f", b[i]); troca_caractere (buffer, '.', ','); //troca o separador decimal de ponto para virgula, que eh o padrao do Brasil fprintf (fp, ";%s\n", buffer); } //imprime os resultados das variaveis for (i=0; i<n; i++) { snprintf (buffer, 266, "x%d =;%f", i+1, x[i]); troca_caractere (buffer, '.', ','); //troca o separador decimal de ponto para virgula, que eh o padrao do Brasil fprintf (fp, "\n%s", buffer); } fclose (fp); //abre o arquivo com o resultado para o usuario visualizar strcpy (buffer, "start "); strcat (buffer, nome_arq); system (buffer); } //fim do procedimento para salvar o resultado em um arquivo .csv printf ("\nDeseja reiniciar o programa? (digite [S] para sim, ou [N] para nao): "); fflush(stdin); op = getchar(); system ("cls"); } while (op == 's' || op == 'S'); return 0; } Jacobi e Gauss Seidel.c //Resolucao de sistemas lineares utilizando os metodos iterativos de Jacobi e Gauss Seidel //Luiz Vinicius Soglia - lvmsoglia@hotmail.com #include <stdio.h> #include <math.h> #include <stdlib.h> #include <string.h> //========================================================================================================== //funcao que implementa a resolução de sistemas lineares pelos metodos iterativos de Jacobi e Gauss Seidel. //n: é a ordem do sistema. //metodo: guarda o método a ser utilizado para a resulução: 1 = jacobi, 2 = gauss seidel. //matriz a[][]: é a matriz dos coeficientes. //matriz b[]: é a matriz dos termos independentes. //matriz x[]: guarda os valores das variaveis após a resolução. //e: é o valor de tolerancia de erro aceitavel no resultado, para ser utilizado como criterio de parada. //k_max: é o numero de iterações maxima permitida. k_max=0 significa ilimitado (mas na realidade faz 100000 iterações, por segurança). //O criterio de parada utilizado é o erro relativo: dr = max|xi(k) - xi(k-1)| / max|xi(k)| //retorna 0 caso haja sucesso, 1 para erros de entrada de argumentos invalidos, 2 para erros de divisão por zero. int iterativos_jacobi_gauss_seidel (int n, int metodo, float a[][n], float b[], float x[], float e, int k_max) { int k, i, j; float s, dr, x_max; float x_aux[n]; //variavel auxiliar que guarda os valores das variaveis xi's da iteracao anterior if (n < 2 || e < 0.0 || k_max < 0) //testa se existe argumentos invalidos {return 1;} if (k_max == 0) //simula um numero de iteracoes "ilimitado" (maximo de 100000 iteracoes) {k_max = 100000;} switch (metodo) //aplica o metodo iterativo escolhido { //Jacobi =============================================================== case 1: { for (k=1; k<=k_max; k++) { for (i=0; i<n; i++) {x_aux[i] = x[i];} //guarda os valores de x da iteracao anterior for (i=0; i<n; i++) { if (a[i][i] != 0.0) //Evita erros de divisao por zero { s = a[i][i]*x_aux[i]; //começa com o termo que nao deveria entrar nas subtrações...para anular sua participação for (j=0; j<n; j++) {s = s - a[i][j]*x_aux[j];} s = b[i] + s; x[i] = s / a[i][i]; } else {return 2;} //Houve erro de divisão por zero } //tolerancia de erro - busca o valor maximo entre |xi(k) - xi(k-1)|/|xi(k)|, testando se é menor do que erro aceitavel dr = fabs(x[0] - x_aux[0]); x_max = fabs(x[0]); for (i=1; i<n; i++) { if (fabs(x[i] - x_aux[i]) > dr) {dr = fabs(x[i] - x_aux[i]);} if (fabs(x[i]) > x_max) {x_max = fabs(x[i]);} } dr = dr / x_max; if (dr < e) //se dr (erro relativo) for menor do que a tolerancia, a solução é aceitavel e termina a execucao do metodo {k++; break;} } } break; //Gauss Seidel ========================================================= case 2: { for (k=1; k<=k_max; k++) { for (i=0; i<n; i++) {x_aux[i] = x[i];} //guarda os valores de x da iteracao anterior for (i=0; i<n; i++) { if (a[i][i] != 0.0) //Evita erros de divisao por zero { s = a[i][i]*x[i]; //começa com o termo que nao deveria entrar nas subtrações...para anular sua participação for (j=0; j<n; j++) {s = s - a[i][j]*x[j];} s = b[i] + s; x[i] = s / a[i][i]; } else {return 2;} //Houve erro de divisão por zero } //tolerancia de erro - busca o valor maximo entre |xi(k) - xi(k-1)|/|xi(k)|, testando se é menor do que erro aceitavel dr = fabs(x[0] - x_aux[0]); x_max = fabs(x[0]); for (i=1; i<n; i++) { if (fabs(x[i] - x_aux[i]) > dr) {dr = fabs(x[i] - x_aux[i]);} if (fabs(x[i]) > x_max) {x_max = fabs(x[i]);} } dr = dr / x_max; if (dr < e) //se dr (erro relativo) for menor do que a tolerancia, a solução é aceitavel e termina a execucao do metodo {k++; break;} } } break; //Caso não exista a opção de método passada para a função, implica em erro. Retorna 1, indicando esse erro. default: return 1; } //fim do switch-case com os metodos iterativos printf ("Foram realizadas %d iteracoes\nErro relativo = max |xi(k) - xi(k-1)| / max |xi(k)| = %f\n\n", k-1, dr); return 0; } //========================================================================================================== //funcao que implementa o criterio de convergencia das linhas. //a[][] é a matriz dos coeficientes. //retorna o valor de alfa. Se alfa < 1 o método de Jacobi ou Gauss Seidel gera uma sequencia convergente //retona -1 caso haja elementos iguais a zero na diagonal principal, o que inviabiliza os metodos iterativos de Jacobi e Gauss Seidel float criterio_linhas (int n, float a[][n]) { float alfa, aux; int i, j; alfa=0.0; for (i=0; i<n; i++) { if (a[i][i] != 0.0) //evita divisões por zero { aux = - fabs(a[i][i]); //inicia alfa com o negativo do termo que nao deve entrar no somatorio, para anular sua participacao for (j=0; j<n; j++) { aux = aux + fabs(a[i][j]); } aux = aux/fabs(a[i][i]); if (aux > alfa) {alfa = aux;} } else {return -1;} //Se houver zeros na diagonal principal retorna -1 indicando esse erro } return alfa; } //========================================================================================================== //funcao que implementa o criterio de convergencia de Sassenfeld (somente para o metodo de Gauss Seidel). //a[][] é a matriz dos coeficientes. //retorna o valor de beta. Se beta < 1 o método de Gauss Seidel gera uma sequencia convergente //retona -1 caso haja elementos iguais a zero na diagonal principal, o que inviabiliza o metodo iterativo de Gauss Seidel float criterio_sassenfeld (int n, float a[][n]) { float beta[n], beta_max, aux; int i, j; beta_max=0; for (i=0; i<n; i++) {beta[i] = 1.0;} //inicializa todos os betas com 1, elemento neutro da multiplicacao for (i=0; i<n; i++) { if (a[i][i] != 0.0) //evita divisões por zero { aux = - fabs(a[i][i]); //inicia alfa com o negativo do termo que nao deve entrar no somatorio, para anular sua participacao for (j=0; j<n; j++) { aux = aux + fabs(a[i][j])*beta[j]; } beta[i] = aux/fabs(a[i][i]); if (beta[i] > beta_max) {beta_max = beta[i];} } else {return -1;} //Se houver zeros na diagonal principal retorna -1 indicando esse erro } return beta_max; } //========================================================================================================== //Função principal int main() { int n, i, j, k_max, metodo, carregamento, teste; float e, alfa, beta; char op, nome_arq[260]; FILE *fp; do { printf ("Resolucao de sistemas lineares por metodos iterativos de Jacobi e Gauss Seidel\n\n"); do { printf ("Digite a ordem do sistema (n), no maximo n=100: "); fflush(stdin); scanf ("%d",&n); } while (n < 2 || n > 100); printf ("\nDigite a opcao do metodo iterativo:\n\n[1] Jacobi\n[2] Gauss Seidel\n\n"); do { printf ("Opcao: "); fflush(stdin); scanf ("%d",&metodo); } while (metodo < 1 || metodo > 2); do { printf ("\nDigite o numero maximo de iteracoes permitidas (digite 0 para ilimitado): "); fflush(stdin); scanf ("%d",&k_max); } while (k_max < 0); do { printf ("\nDigite a tolerancia de erro aceitavel: "); fflush(stdin); scanf ("%f",&e); } while (e < 0.0); printf ("\nDigite a opcao para o carregamento do sistema linear:\n\n[1] Digitar os dados aqui\n[2] Atraves de um arquivo .txt\n\n"); do { printf ("Opcao: "); fflush(stdin); scanf ("%d",&carregamento); } while (carregamento < 1 || carregamento > 2); //Cria as matrizes float a[n][n], x[n], b[n]; //cria as matrizes dos coeficientes (A), das variaveis (X) e dos termos independentes (B) //faz o carregamento da matriz do sistema de acordo com a opcao escolhida switch (carregamento) { //digita a matriz case 1: for (i=0; i<n; i++) { do { system ("cls"); printf ("Digite os elementos da linha %d:\n\n", i+1); for (j=0; j<n; j++) { printf ("a[%d][%d] = ", i+1, j+1); scanf ("%f", &a[i][j]); } printf ("\nb[%d] = ", i+1); scanf ("%f", &b[i]); printf ("\nOs valores digitados estao corretos? (digite [S] para sim, ou [N] para nao): "); fflush(stdin); op = getchar(); } while (op != 's' && op != 'S'); } do { system ("cls"); printf ("Digite a soluca inicial:\n\n"); for (i=0; i<n; i++) { printf ("x[%d] = ", i+1); scanf ("%f", &x[i]); } printf ("\nOs valores digitados estao corretos? (digite [S] para sim, ou [N] para nao): "); fflush(stdin); op = getchar(); } while (op != 's' && op != 'S'); break; //carrega do arquivo case 2: do { printf ("\nDigite o caminho do arquivo de texto (com a extensao) que contem os dados:\n"); fflush(stdin); scanf ("%259[^\n]",nome_arq); fp=fopen(nome_arq,"r"); if (!fp) { printf ("\nErro na abertura do arquivo! Pressione [ENTER] para continuar\n"); fflush(stdin); op = getchar(); } } while(!fp); //inicializa e lê os coeficientes das matrizes A e B e a solução inicial for (i=0; i<n; i++) { for (j=0; j<n; j++) { a[i][j]=0.0; fscanf (fp, "%f", &a[i][j]); //matriz A } b[i]=0.0; fscanf (fp, "%f", &b[i]); //matriz B } for (i=0; i<n; i++) {fscanf (fp, "%f", &x[i]);} //solucao inicial fclose(fp); break; default: printf ("\nOcorreu um erro no carregamento do sistema! Pressione [ENTER] para sair\n"); fflush(stdin); op = getchar(); return 0; } //fim do carregamento da matriz //criterio de convergencia das linhas system ("cls"); printf ("Deseja verificar a convergencia pelo criterio das linhas?\nDigite [S] para sim e [N] para nao: "); fflush(stdin); op = getchar(); if (op == 's' || op == 'S') { alfa = criterio_linhas (n, a); if (alfa >= 0) { if (alfa < 1) {printf ("\nalfa = %f. alfa < 1, convergencia garantida!\n", alfa);} else {printf ("\nalfa = %f. alfa >= 1, nao existe convergencia garantida!\n", alfa);} } else { printf ("\nHa elementos iguais a zero na diagonal principal, isso inviabiliza\nos metodos iterativos!"); printf (" Tente reagrupar as equacoes para que nao existam zeros\nna diagonal principal!\n\nPressione [ENTER] para sair\n"); fflush(stdin); op = getchar(); return 0; } } //criterio de convergencia de Sassenfeld (somente para o metodo de Gauss Seidel) if (metodo == 2) //metodo de Gauss Seidel { printf ("\nDeseja verificar a convergencia pelo criterio de Sassenfeld?\nDigite [S] para sim e [N] para nao: "); fflush(stdin); op = getchar(); if (op == 's' || op == 'S') { beta = criterio_sassenfeld (n, a); if (beta >= 0) { if (beta < 1) {printf ("\nbeta = %f. beta < 1, convergencia garantida!\n", beta);} else {printf ("\nbeta = %f. beta >= 1, nao existe convergencia garantida!\n", beta);} } else { printf ("\nHa elementos iguais a zero na diagonal principal, isso inviabiliza o metodo\nde Gauss Seidel!"); printf (" Tente reagrupar as equacoes para que nao existam\nzeros na diagonal principal!\n\nPressione [ENTER] para sair\n"); fflush(stdin); op = getchar(); return 0; } } } printf ("\nDados carregados! Pressione [ENTER] para continuar e resolver o sistema linear\n"); fflush(stdin); op = getchar(); system ("cls"); //Chama a função que aplica o metodo iterativo - retorna zero para teste caso haja sucesso teste = iterativos_jacobi_gauss_seidel (n, metodo, a, b, x, e, k_max); if (teste == 1) //se a função retornar 1, argumentos invalidos foram passados para a função { printf ("Erro! Argumentos invalidos foram digitados!\n\nPressione [ENTER] para sair\n"); fflush(stdin); op = getchar(); return 0; } if (teste == 2) //se a função retornar 2 houve erro de divisão por zero durante o calculo { printf ("Ocorreu erro de divisao por zero!\n"); printf ("Tente reagrupar as equacoes para que nao existam zeros na diagonal principal!\n\nPressione [ENTER] para sair\n"); fflush(stdin); op = getchar(); return 0; } //exibe o resultado na tela printf ("Resultados:\n\n"); for (i=0; i<n; i++) {printf ("x%d = %f\n", i+1, x[i]);} printf ("\nDeseja reiniciar o programa? (digite [S] para sim, ou [N] para nao): "); fflush(stdin); op = getchar(); system ("cls"); } while (op == 's' || op == 'S'); return 0; }
Compartilhar