This repository has been archived on 2019-08-08. You can view files and clone it, but cannot push or open issues or pull requests.
s4-c/DS2/E1.c

207 lines
7.1 KiB
C

/* Résolution du système par la méthode de Gauss-Seidel */
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
// 1)
int diagdom(int n, double A[n][n]) {
int i, j;
double S; // La somme de l'équation (2)
for (i = 0; i <= n-1; i++) {
// Pour tout i
S = 0;
for (j = 0; j <= n-1; j++) {
if (j != i) {
S += fabs(A[i][j]);
}
}
if (fabs(A[i][i]) < S) {
return 0;
}
}
return 1;
}
// 2) a)
double norm(int n, double *x) {
double carre = 0; // Carré de la norme
double *xi; // Pointeur qui se déplacera sur les composantes du vecteur
for (xi = x; xi < x + n; xi++) {
carre += pow(*xi, 2);
}
return sqrt(carre);
}
int main(int argc, char *argv[]) {
// 2) b)
int n;
printf("Saisissez l'ordre n du système : ");
scanf("%d", &n);
// Saisie de la matrice
double A[n][n];
int i, j;
for (i = 0; i <= n-1; i++) {
for (j = 0; j <= n-1; j++) {
printf("Saisissez l'élément de A aux coordonnées (%3d;%3d) : ", i, j);
scanf("%lf", &A[i][j]);
}
}
// Saisie du second membre y
double Y[n];
for (i = 0; i <= n-1; i++) {
printf("Saisissez la composante numéro %3d du vecteur second membre y : ", i);
scanf("%lf", &Y[i]);
}
// Saisie du vecteur initial x
double X[n];
for (i = 0; i <= n-1; i++) {
printf("Saisissez la composante numéro %3d du vecteur initial x⁽⁰⁾ : ", i);
scanf("%lf", &X[i]);
}
// Saisie de la précision epsilon (pas demmandé explicitement mais marqué
// comme "donné", donc dans le doute on le demande)
double E;
printf("Saisissez la précision Epsilon : ");
scanf("%lf", &E);
printf("\n");
// Affichage de la matrice (pas demmandé mais utile)
for (i = 0; i <= n-1; i++) {
for (j = 0; j <= n-1; j++) {
printf("%11lf", A[i][j]);
}
printf("\n");
}
// Vérification si la matrice est à diagonale dominante
if (!diagdom(n, A)) {
printf("La matrice n'est pas à diagonale dominante.\n");
return 1;
}
// Application de la méthode itérative
double Xp[n]; // Vecteur itéré précédent
double R[n]; // Vecteur résidu
int it = 0; // Nombre d'itérations
double S1; // Première somme de (1)
double S2; // Deuxième somme de (1)
do {
// L'utilisation d'une boucle do...while permet d'éviter
// d'initialiser Xp et R avant la boucle. Du coup la première
// itération est forcée mais le cas où 0 itération serait
// necessaire est plutôt rare
// Une boucle while classique aurait aussi tout à fait possible
it++; // Nouvelle itération
// On copie X → Xp
for (i = 0; i <= n-1; i++) {
Xp[i] = X[i];
}
// On applique (1)
for (i = 0; i <= n-1; i++) {
// Première somme de (1)
S1 = 0;
for (j = 0; j <= i-1; j++) {
S1 += A[i][j] * X[j];
}
// Deuxième somme de (1)
S2 = 0;
for (j = i+1; j <= n-1; j++) {
S2 += A[i][j] * Xp[j];
}
X[i] = (1/A[i][i])*(Y[i]-S1-S2);
}
// Calcul de r
for (i = 0; i <= n-1; i++) {
R[i] = X[i] - Xp[i];
}
} while (norm(n, R) >= E);
// Affichage du résultat
printf("X =\n");
for (i = 0; i <= n-1; i++) {
printf("%lf\n", X[i]);
}
printf("%d itérations ont été nécessaire pour arriver à la précision %11lf.\n", it, E);
return 0;
}
// 2) c)
// Saisissez l'ordre n du système : 3
// Saisissez l'élément de A aux coordonnées ( 0; 0) : 3
// Saisissez l'élément de A aux coordonnées ( 0; 1) : 1
// Saisissez l'élément de A aux coordonnées ( 0; 2) : 1
// Saisissez l'élément de A aux coordonnées ( 1; 0) : 1
// Saisissez l'élément de A aux coordonnées ( 1; 1) : -3
// Saisissez l'élément de A aux coordonnées ( 1; 2) : 2
// Saisissez l'élément de A aux coordonnées ( 2; 0) : -1
// Saisissez l'élément de A aux coordonnées ( 2; 1) : 2
// Saisissez l'élément de A aux coordonnées ( 2; 2) : 4
// Saisissez la composante numéro 0 du vecteur second membre y : -2
// Saisissez la composante numéro 1 du vecteur second membre y : 1
// Saisissez la composante numéro 2 du vecteur second membre y : 5
// Saisissez la composante numéro 0 du vecteur initial x⁽⁰⁾ : 1
// Saisissez la composante numéro 1 du vecteur initial x⁽⁰⁾ : 1
// Saisissez la composante numéro 2 du vecteur initial x⁽⁰⁾ : 1
// Saisissez la précision Epsilon : 0.0000001
//
// 3.000000 1.000000 1.000000
// 1.000000 -3.000000 2.000000
// -1.000000 2.000000 4.000000
// X =
// -1.000000
// 0.000000
// 1.000000
// 14 itérations ont été nécessaire pour arriver à la précision 0.000000.
// Saisissez l'ordre n du système : 4
// Saisissez l'élément de A aux coordonnées ( 0; 0) : 2
// Saisissez l'élément de A aux coordonnées ( 0; 1) : -1
// Saisissez l'élément de A aux coordonnées ( 0; 2) : 0
// Saisissez l'élément de A aux coordonnées ( 0; 3) : 0
// Saisissez l'élément de A aux coordonnées ( 1; 0) : -1
// Saisissez l'élément de A aux coordonnées ( 1; 1) : 2
// Saisissez l'élément de A aux coordonnées ( 1; 2) : -1
// Saisissez l'élément de A aux coordonnées ( 1; 3) : 0
// Saisissez l'élément de A aux coordonnées ( 2; 0) : 0
// Saisissez l'élément de A aux coordonnées ( 2; 1) : -1
// Saisissez l'élément de A aux coordonnées ( 2; 2) : 2
// Saisissez l'élément de A aux coordonnées ( 2; 3) : -1
// Saisissez l'élément de A aux coordonnées ( 3; 0) : 0
// Saisissez l'élément de A aux coordonnées ( 3; 1) : 0
// Saisissez l'élément de A aux coordonnées ( 3; 2) : -1
// Saisissez l'élément de A aux coordonnées ( 3; 3) : 2
// Saisissez la composante numéro 0 du vecteur second membre y : -3
// Saisissez la composante numéro 1 du vecteur second membre y : 1
// Saisissez la composante numéro 2 du vecteur second membre y : 4
// Saisissez la composante numéro 3 du vecteur second membre y : -4
// Saisissez la composante numéro 0 du vecteur initial x⁽⁰⁾ : 1
// Saisissez la composante numéro 1 du vecteur initial x⁽⁰⁾ : 1
// Saisissez la composante numéro 2 du vecteur initial x⁽⁰⁾ : 1
// Saisissez la composante numéro 3 du vecteur initial x⁽⁰⁾ : 1
// Saisissez la précision Epsilon : 0.0000001
//
// 2.000000 -1.000000 0.000000 0.000000
// -1.000000 2.000000 -1.000000 0.000000
// 0.000000 -1.000000 2.000000 -1.000000
// 0.000000 0.000000 -1.000000 2.000000
// X =
// -1.000000
// 1.000000
// 2.000000
// -1.000000
// 38 itérations ont été nécessaire pour arriver à la précision 0.000000.
// (notons que Epsilon n'est pas affiché totalement malgré le fait qu'il soit bien stocké en mémoire !)
// De plus, saisir un Epsilon trop petit pourrait être considéré comme zéro par le programme et ne pas
// fonctionner correctement (division par 0)