IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Votre avis pour améliorer mon code (opérations matricielles)


Sujet :

C

  1. #21
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    - Du point de vue de l'accès aux éléments du tableau, le deux méthodes sont équivalentes.

    - Du point de vue de la réussite des allocations, la seconde méthode risque d'échouer pour les très gros tableaux la où la méthode 1 peut réussir : on a plus de chance de pouvoir allouer "beaucoup" de tableaux de taille "raisonnable" que d'en allouer un très grand. On peut dans ce cas augmenter ses chances en allouant le gros tableau très tôt dans le programme, avant la fragmentation du tas.

    - La seconde méthode peut compliquer considérablement le codage d'un redimensionnement du tableau qui modifie le nombre de colonnes.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  2. #22
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2010
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 42
    Points : 21
    Points
    21
    Par défaut
    Merci pour les précisions des deux derniers post.

    Voilà, j'ai codé mes fonctions de base pour les matrices, création, destruction, affichage, j'ai choisi de coder la première méthode, comme diogène m'avais déjà codé la seconde.

    Les fonctions :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    //Création Matrice
     
    struct Matrice *CreerMatrice(int nbreligne,int nbrecolonne)
    {
        int i, j;
     
        Matrice *Matr = malloc(sizeof(Matrice));
        if (Matr != NULL)
        {
            Matr->nbreligne = nbreligne;
            Matr->nbrecolonne = nbrecolonne;
            Matr->matrice = malloc(nbreligne*sizeof(double*));
     
            if (Matr->matrice != NULL)
            {
                for (i = 0; i < nbreligne; i++)
                {
                    Matr->matrice[i] = malloc(nbrecolonne*sizeof(double));
     
                    if (Matr->matrice[i] == NULL)
                    {
                        printf("Echec d'allocation pour Matr->matrice[%d]",i);
                        DetruireMatrice(Matr);
                        Matr = NULL;
                    }
                }
            }
            else
            {
                printf("Echec d'allocation Matr->matrice");
                DetruireMatrice(Matr);
                Matr = NULL;
            }
        }
        else
        {
            printf("Echec d'allocation structure Matr");
            DetruireMatrice(Matr);
            Matr = NULL;
        }
     
        //Initialisation de la matrice
     
        for (i = 0; i < Matr->nbreligne; i++)
        {
            for (j = 0; j < Matr->nbrecolonne; j++)
            {
                Matr->matrice[i][j] = 0.0;
            }
        }
     
        return Matr;
    }
     
    //Destruction matrice
     
    void DetruireMatrice(Matrice *Matr)
    {
        int i;
     
        for (i = 0; i < Matr->nbreligne; i++)
        {
            free(Matr->matrice[i]);
        }
     
        free(Matr->matrice);
        free(Matr);
    }
     
    //Afficher matrice
     
    void AfficherMatrice(Matrice *Matr)
    {
        int i, j;
     
        for (i = 0; i < Matr->nbreligne; i++)
        {
            printf("| ");
     
            for (j = 0; j < Matr->nbrecolonne; j++)
            {
                printf(" %f", Matr->matrice[i][j]);
            }
     
            printf(" |\n");
        }
    }
    J'espère qu'il n'y manque rien.

  3. #23
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Ton code pour CréerMatrice() est à revoir (je sais, je suis un emm...).

    Les dispositions prises pour tester les allocations sont inadéquates :

    Supposons que l'allocation pour Matr->matrice[i] échoue, tu appelles DetruireMatrice(). Cette dernière fonction va faire un free() pour tous les Matr->matrice[k] y compris pour ceux qui n'ont pas encore été alloués (pour k>i). Conséquence : Plantage !

    Deux solutions possibles :

    - Avant de commencer les allocations des Matr->matrice[i], les mettre tous à NULL. Alors en cas d'échec d'une allocation, DetruireMatrice() fera des free(NULL) pour ceux qui n'ont pas encore été alloué, ce qui est correct.

    - Faire toutes les allocations des Matr->matrice[i] sans se préoccuper de la réussite ou de l'échec puis vérifier que tous les Matr->matrice[i] sont différents de NULL. Si ce n'est pas le cas, on appelle DetruireMatrice().

    (personnellement, je préfère la première solution)
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  4. #24
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2010
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 42
    Points : 21
    Points
    21
    Par défaut
    Non pas un emm ... je suis là pour apprendre alors tant qu'a faire autant que ça soit impec !

    Voilà j'ai modifié cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    struct Matrice *CreerMatrice(int nbreligne,int nbrecolonne)
    {
        int i, j;
     
        Matrice *Matr = malloc(sizeof(Matrice));
        if (Matr != NULL)
        {
            Matr->nbreligne = nbreligne;
            Matr->nbrecolonne = nbrecolonne;
            Matr->matrice = malloc(nbreligne*sizeof(double*));
     
            if (Matr->matrice != NULL)
            {
                //Initialisation des pointeurs sur les lignes
     
                for (i = 0; i < nbreligne; i++)
                {
                    Matr->matrice[i] = NULL;
                }
     
                for (i = 0; i < nbreligne; i++)
                {
                    Matr->matrice[i] = malloc(nbrecolonne*sizeof(double));
     
                    if (Matr->matrice[i] == NULL)
                    {
                        printf("Echec d'allocation pour Matr->matrice[%d]",i);
                        DetruireMatrice(Matr);
                        Matr = NULL;
                    }
                }
            }
            else
            {
                printf("Echec d'allocation Matr->matrice");
                DetruireMatrice(Matr);
                Matr = NULL;
            }
        }
        else
        {
            printf("Echec d'allocation structure Matr");
            DetruireMatrice(Matr);
            Matr = NULL;
        }
     
        //Initialisation de la matrice
     
        for (i = 0; i < Matr->nbreligne; i++)
        {
            for (j = 0; j < Matr->nbrecolonne; j++)
            {
                Matr->matrice[i][j] = 0.0;
            }
        }
     
        return Matr;
    }

  5. #25
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Il y a encore des choses à revoir :
    1-
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        for (i = 0; i < Matr->nbreligne; i++)
            for (j = 0; j < Matr->nbrecolonne; j++)
                Matr->matrice[i][j] = 0.0;
    Lorsque Matr est NULL parce qu'une des allocation a échoué, Matr->nbreligne, Matr->nbrecolonne et Matr->matrice[i][j] = 0.0 plantent !

    2-
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
                for (i = 0; i < nbreligne; i++)
                {
                    Matr->matrice[i] = malloc(nbrecolonne*sizeof(double));
                    if (Matr->matrice[i] == NULL)
                    {
                        printf("Echec d'allocation pour Matr->matrice[%d]",i);
                        DetruireMatrice(Matr);
                        Matr = NULL;
                    }
                }
    Si pour une valeur de i<nbreligne-1, une allocation échoue, Matr est détruit, mais la boucle continue et le programme plante au tour suivant.

    On peut faire, par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    Matrice *CreerMatrice(int nbreligne,int nbrecolonne)
    {
        int i, j;
        int AllocOK;
        Matrice *Matr = malloc(sizeof(Matrice));
        AllocOK = Matr != NULL ;
        if (AllocOK)
        {
            Matr->nbreligne = nbreligne;
            Matr->nbrecolonne = nbrecolonne;
            Matr->matrice = malloc(nbreligne*sizeof(double*));
            AllocOK = Matr->matrice != NULL ;
            if (AllocOK)
            {
                for (i = 0; i < nbreligne; i++) Matr->matrice[i] = NULL;
                for (i = 0; i < nbreligne && AllocOK; i++)
                {
                    Matr->matrice[i] = malloc(nbrecolonne*sizeof(double));
                    AllocOK = Matr->matrice[i] != NULL ;
                }
            }
        }
        if(AllocOK)
        {
           for (i = 0; i < Matr->nbreligne; i++)
               for (j = 0; j < Matr->nbrecolonne; j++)
                   Matr->matrice[i][j] = 0.0;
        }
        else
        {
            printf("Echec d'allocation structure Matr");
            DetruireMatrice(Matr);
            Matr = NULL;
        }
        return Matr;
    }
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  6. #26
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2010
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 42
    Points : 21
    Points
    21
    Par défaut
    Ok merci,

    Ça me fais une règle à retenir dans mes tables de la loi :

    -------------------------------------------------------------------------------------
    |- A la conséquence d'une ligne de code sur les suivantes tu prendras garde ! |
    -------------------------------------------------------------------------------------

    ça ferrais mieux avec Charlton Heston dans le rôle de Moïse, des éclairs qui zèbre le ciel et des tables en pierre mais bon ...

    J'arrange cela dès demain.

  7. #27
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2010
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 42
    Points : 21
    Points
    21
    Par défaut
    Bonjour,

    Je fais peu être une erreur logique, mais je me demande si il n'y a pas une petite erreur ici :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for (i = 0; i < nbreligne && AllocOK; i++)
                {
                    Matr->matrice[i] = malloc(nbrecolonne*sizeof(double));
                    AllocOK = Matr->matrice[i] == NULL ;
                }
    ça ne devrait pas plutôt être ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for (i = 0; i < nbreligne && AllocOK; i++)
                {
                    Matr->matrice[i] = malloc(nbrecolonne*sizeof(double));
                    AllocOK = Matr->matrice[i] != NULL ;
                }
    Parce qu'il me semble que sinon dès le second passage on sort de la boucle.

  8. #28
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Oui, tu as raison (comme quoi tu as raison de faire attention et de ne pas pomper simplement).
    Je corrige mon post.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  9. #29
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2010
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 42
    Points : 21
    Points
    21
    Par défaut
    Oui merci, j'essaye au maximum de bien tout comprendre, de toute façon je n'aime pas trop pomper un truc que je pige pas, parce qu'à ce moment là autant tout allez pomper sur le net, mais je vois pas trop l'intérêt.

    Voilà j'ai modifié tout cela j'ai donc ce code pour les diverses fonctions :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    #include <stdio.h>
    #include <stdlib.h>
     
    #include "GOperations_matrice_de_base.h"
     
     
     
    //Création Matrice
     
    struct Matrice *CreerMatrice(int nbreligne,int nbrecolonne)
    {
        int i, j;
     
        Matrice *Matr = malloc(sizeof(Matrice));
        int AllocationOk = Matr != NULL; //Initialisation de la variable test allocation
        if (AllocationOk)
        {
            Matr->nbreligne = nbreligne;
            Matr->nbrecolonne = nbrecolonne;
            Matr->matrice = malloc(nbreligne*sizeof(double*));
            AllocationOk = Matr->matrice != NULL; //Nouvelle valeur pour la variable test allocation
     
            if (AllocationOk)
            {
                //Initialisation des pointeurs sur les lignes
     
                for (i = 0; i < nbreligne; i++)
                {
                    Matr->matrice[i] = NULL;
                }
     
                for (i = 0; i < nbreligne && AllocationOk; i++)
                {
                    Matr->matrice[i] = malloc(nbrecolonne*sizeof(double));
                    AllocationOk = Matr->matrice[i] != NULL; //Nouvelle valeur pour la variable test allocation
                }
            }
        }
     
    if (AllocationOk)
    {
        //Initialisation de la matrice
     
        for (i = 0; i < Matr->nbreligne; i++)
        {
            for (j = 0; j < Matr->nbrecolonne; j++)
            {
                Matr->matrice[i][j] = 0.0;
            }
        }
    }
    else
    {
        printf("Echec d'allocation matrice");
        DetruireMatrice(Matr);
        Matr = NULL;
    }
     
        return Matr;
    }
     
    //Destruction matrice
     
    void DetruireMatrice(Matrice *Matr)
    {
        int i;
     
        for (i = 0; i < Matr->nbreligne; i++)
        {
            free(Matr->matrice[i]);
        }
     
        free(Matr->matrice);
        free(Matr);
    }
     
    //Afficher matrice
     
    void AfficherMatrice(Matrice *Matr)
    {
        int i, j;
     
        for (i = 0; i < Matr->nbreligne; i++)
        {
            printf("| ");
     
            for (j = 0; j < Matr->nbrecolonne; j++)
            {
                printf(" %f", Matr->matrice[i][j]);
            }
     
            printf(" |\n");
        }
    }
    Donc je pense que cette fois tout est plus ou moins ok, je vais donc recorder les 3 fonctions transposé, produit matriciel et inverse, enrichie de ce que j'ai déjà apprit ici, cela risque d'être long, notamment pour le code de la matrice inverse par méthode de Gauss qui est assez long, mais il devrais se simplifier grâce aux fonctions "de base" que l'on viens de créer.
    Je reposte dès que j'ai fini la transposée.

  10. #30
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    La fonction DetruireMatrice() est intimement liée à l'écriture de CreerMatrice() d'autant plus qu'elle est appelée dans CreerMatrice() pour faire le ménage en cas de problèmes (ce qui est bien commode). Cela impose de regarder attentivement les deux codes simultanément sachant que DetruireMatrice() peut alors être appelée à détruire une Matrice incomplétement formée.

    Notamment, elle sera appelée lorsque :

    - Matr est NULL
    - ou sinon Matr->matrice est NULL
    - ou sinon un Matr->matrice[i] est NULL (les autres sont NULL ou correctement alloués)

    Ta fonction DetruireMatrice() plante alors dans certains cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void DetruireMatrice(Matrice *Matr)
    {
        int i; 
        for (i = 0; i < Matr->nbreligne; i++) // plante si Matr == NULL
        {
            free(Matr->matrice[i]); // plante si Matr == NULL ou Matr->matrice == NULL
        } 
        free(Matr->matrice); // plante si Matr == NULL
        free(Matr);
    }
    En général, quand on passe à une fonction un pointeur sur structure et qu'on essaie d'accéder à un champ (comme dans DetruireMatrice() ou AfficherMatrice()) , on doit se demander si le pointeur peut être NULL lors de l'appel.
    - Si la réponse de principe est oui, il faut tester le pointeur et prendre les dispositions adéquates si il est NULL.
    - Si la réponse de principe est non, on n'a pas intérêt à tester le pointeur mais à laisser carrément le programme planter pour signaler sans tarder une utilisation incorrecte de la fonction.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  11. #31
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2010
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 42
    Points : 21
    Points
    21
    Par défaut
    Bonjour,

    Après quelques jours à m'être consacré à la sécurité informatique, je reviens à mon programme voilà pour le moment la fonction transposée :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    struct Matrice *Transposee(struct Matrice *A)
    {
        int i = 0, j = 0;
        Matrice *T;
     
        //On crée la matrice transposé T
     
        T = CreerMatrice(A->nbrecolonne, A->nbreligne);
     
        //On effectue la transposé de la matrice entré en paramètre
     
        if (T != NULL)
        {
            for (i = 0; i < T->nbreligne; i++)
            {
                for (j = 0; j < T->nbrecolonne; j++)
                {
                    T->matrice[i][j] = A->matrice[j][i];
                }
            }
        }
        else
        {
            printf("\n\nerreur création matrice T = NULL");
        }
     
        //On retourne le pointeur sur la structure transposé nouvellement créé
     
        return T;
    }
    J'ai également modifié ma fonction détruire matrice et afficher matrice pour vérifier que Matr n'est pas égale à NULL au départ suite à la suggestion de diogène.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    //Destruction matrice
     
    void DetruireMatrice(Matrice *Matr)
    {
        if (Matr != NULL)
        {
            int i;
     
            for (i = 0; i < Matr->nbreligne; i++)
            {
                free(Matr->matrice[i]);
            }
     
            free(Matr->matrice);
            free(Matr);
        }
        else
        {
            printf("\n\nErreur : Matr = NULL");
        }
    }
     
    //Afficher matrice
     
    void AfficherMatrice(Matrice *Matr)
    {
        if (Matr != NULL)
        {
            int i, j;
     
            for (i = 0; i < Matr->nbreligne; i++)
            {
                printf("| ");
     
                for (j = 0; j < Matr->nbrecolonne; j++)
                {
                    printf(" %f", Matr->matrice[i][j]);
                }
     
                printf(" |\n");
            }
        }
        else
        {
            printf("\n\nErreur : Matr = NULL");
        }
    }
    Voilà j'attends vos commentaire et idée d'amélioration.

    Je me suis posé une question a propos de ma matrice transposée, lorsque je fais quelque chose du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    A = CreerMatrice(2,3);
    T = Transposee(Transposee(A));
    AfficherMatrice(T);
    DetruireMatrice(A);
    DetruireMatrice(T);
    Je me demandais comment supprimer la matrice T créé en mémoire par le premier transposée, parce qu'il me semble que dans cette configuration les matrice transposée intermédiaire ne sont jamais supprimé, ce qui peu causé des problèmes (fuite).

  12. #32
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Je me demandais comment supprimer la matrice T créé en mémoire par le premier transposée, parce qu'il me semble que dans cette configuration les matrice transposée intermédiaire ne sont jamais supprimé, ce qui peu causé des problèmes (fuite).
    Il est sûr que ce genre d'écriture pose problème. Tu dois absolument récupérer les adresses des struct Matrice créées par allocation dynamique.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    A = CreerMatrice(2,3);
    Q = Transposee(A);
    T = Transposee(Q);
    AfficherMatrice(T);
    DetruireMatrice(A);
    DetruireMatrice(T);
    DetruireMatrice(Q);
    C'est une très mauvaise habitude que de faire des printf() dans les fonctions. Cela limite la souplesse d'utilisation. Il vaut mieux renvoyer un indicateur d'erreur et laisser l'utilisateur faire ce qu'il veut de cette information.
    Pour Transposee() et CreerMatrice()n le retour de NULL fait parfaitement l'affaire.
    Pour DetruireMatrice(), passer NULL pour Matr n'est même pas une erreur et ne rien faire lorsque Matr est NULL rend la fonction bien plus souple à utiliser (pour la même raison que free(NULL) est légal et ne fait rien et que tu as pris avantage de ce comportement dans DetruireMatrice()).
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  13. #33
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2010
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 42
    Points : 21
    Points
    21
    Par défaut
    Ok je vais supprimer les messages d'erreurs.

    Et réfléchir pour récupérer mes adresses intermédiaire pour pouvoir libérer la mémoire ensuite.

    Merci diogene.

  14. #34
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2010
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 42
    Points : 21
    Points
    21
    Par défaut
    Bonjour,

    Excuse moi concernant mon dernier post, j'avais mal lus, je n'avais pas vus que tu m'avais fourni la réponse concernant le problème de la transposée de la transposé

    J'avais également pensée à détruire la matrice placé en paramètre à la fin de la fonction, ça m'aurais bien détruit les matrice intermédiaires, mais malheureusement la matrice de départ également, donc je ne vais pas compliqué les choses pour au final pas grand chose, je vais opté pour ta méthode.

    Sinon j'ai créé ma fonction Produit matriciel, la voici :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    struct Matrice *ProduitMatriciel (struct Matrice *A, struct Matrice *B)
    {
        int i, j, n;
     
        Matrice *P = NULL;
     
        //Verification de la compatibilité des matrices pour le produit
     
        if (A->nbrecolonne != B->nbreligne)
        {
            printf("\n\nMatrices incompatible pour le produit");
        }
     
        else
        {
            P = CreerMatrice(A->nbreligne, B->nbrecolonne);
     
            //Calcul du produit matriciel
     
            for (i = 0; i < A->nbreligne; i++)
            {
                for (j = 0; j < B->nbrecolonne; j++)
                {
                    for (n = 0; n < A->nbrecolonne; n++)
                    {
                        P->matrice[i][j] = P->matrice[i][j] + (A->matrice[i][n])*(B->matrice[n][j]);
                    }
                }
            }
        }
     
        return P;
    }
    J'y ai quand même mis un message d'erreur à l'intérieur, je sais pas si j'ai bien fais tu me donnera ton avis, car ici il me semblais utile d'indiquer d'où provenais l'erreur.

  15. #35
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    J'y ai quand même mis un message d'erreur à l'intérieur, je sais pas si j'ai bien fais tu me donnera ton avis, car ici il me semblais utile d'indiquer d'où provenais l'erreur.
    Tu sais maintenant ce que j'en pense. Je suis partisan de ne pas mettre de message d'erreur et de renvoyer NULL pour indiquer au programme appelant une erreur. Si tu tiens à préciser le type de l'erreur, par exemple faire la différence entre une erreur d'allocation et une erreur dans la valeur des paramètres, le mieux est de renvoyer un mot d'état.

    Sinon, les mêmes critiques qu'auparavant : tu ne testes pas correctement la réussite ou l'échec :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    struct Matrice *ProduitMatriciel (struct Matrice *A, struct Matrice *B)
    {
        int i, j, n; 
        Matrice *P = NULL; 
        //Verification de la compatibilité des matrices pour le produit 
        if (A->nbrecolonne == B->nbreligne)
        {
            P = CreerMatrice(A->nbreligne, B->nbrecolonne);
            if(p != NULL)
            {
                 //Calcul du produit matriciel
                for (i = 0; i < A->nbreligne; i++)
                {
                   for (j = 0; j < B->nbrecolonne; j++)
                   {
                       for (n = 0; n < A->nbrecolonne; n++)
                       {
                           P->matrice[i][j] += A->matrice[i][n] * B->matrice[n][j];
                       }
                   } 
                }
            }
       }
       return P;
    }
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  16. #36
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2010
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 42
    Points : 21
    Points
    21
    Par défaut
    Ok j'en prend bonne note, je n'étais pas sur que ta remarque concernait tout les printf dans les fonctions, je vais corriger cela.

    Sinon oui, je suis vraiment pas possible ! cela fais dix fois que l'on rabâche de vérifier que le pointeur sur la structure n'est pas égal à NULL et je trouve encore le moyen de l'oublier
    D'ailleurs ne faudrait il pas vérifier les pointeurs A et B placé en paramètre également ?

    Je reposte lorsque j'ai fini la dernière fonction, je vais essayé de faire attention cette fois !

  17. #37
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Ok j'en prend bonne note, je n'étais pas sur que ta remarque concernait tout les printf dans les fonctions, je vais corriger cela.
    Il faut garder la généralisation d'emploi de tes fonctions. Leur ajouter des effets de bords qui ne sont pas nécessaires à leur fonctionnement (comme ces printf()) ajoute en général des contraintes à leur utilisation (par exemple, il faut que le programme qui utilise la fonction ait une console pour afficher, et la fonction peut poser des problèmes si elle est utilisée avec un programme en mode fenêtré, alors que la fonction "obtenir le produit de deux matrices" n'est pas du tout concernée par les conditions d'affichage du programme).

    D'ailleurs ne faudrait il pas vérifier les pointeurs A et B placé en paramètre également ?
    De fait, la fonction ProduitMatriciel() n'a pas de sens si l'un au moins des pointeurs est NULL. Il fait donc partie du contrat avec l'utilisateur de passer l'adresse de deux Matrice qui existent. (La situation est donc un peu différente du cas de DetruireMatrice() où on avait trouver un avantage à traiter le cas de l'argument NULL)
    On peut essayer de sécuriser la fonction contre une erreur de valeurs des paramètres. Mais, on n'arrivera pas à le faire totalement : ces pointeurs peuvent pointer dans la nature (ailleurs que NULL ou vers une Matrice) sans qu'on puisse le détecter et alors provoquer un plantage. C'est pourquoi, à mon avis, le programmeur peut choisir ici l'option qu'il préfère.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  18. #38
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2010
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 42
    Points : 21
    Points
    21
    Par défaut
    Bonjour,

    Donc voici ma fonction d'inversion de matrice par la méthode des pivots de Gauss, j'espère avoir été claire dans mes commentaires.
    Les print() sont destiné à être effacé, ils m'aidaient juste à vérifier le bon déroulement de l'algorithme.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
     
    #include "fonction.h"
    #include "../Operations_de_base/GOperations_matrice_de_base.h"
     
    #define LimiteMax 1e-10//define à modifier en fonction des nombres traité dans la matrice si ceux ci très petit
    #define LimiteMin -1e-10
     
    struct Matrice *Inverse(struct Matrice *matrice)
    {
        int n, i, j, k , l, g, cPi = 0, cPj = 0, MatriceNonInversible = 0;
        double Pivot = 0.0, C;
     
        //Allocation dynamique pour les deux matrices Mb et Ib ainsi que pour les differents tableaux de coordonnées
     
        Matrice *Mb, *Ib = NULL, *I, *M;
     
        M = CreerMatrice(matrice->nbreligne,matrice->nbrecolonne);
     
        /*On copie la matrice "matrice" entrée en paramètre dans une matrice M pour pouvoir conserver notre
        matrice de base*/
     
        for (i = 0; i < matrice->nbreligne; i++)
        {
            for (j = 0; j < matrice->nbrecolonne; j++)
            {
                M->matrice[i][j] = matrice->matrice[i][j];
            }
        }
     
        //Allocation pour les autres matrice dont nous aurons besoin
     
        Mb = CreerMatrice(M->nbreligne,M->nbrecolonne);
        Ib = CreerMatrice(M->nbreligne,M->nbrecolonne);
        I = CreerMatrice(M->nbreligne,M->nbrecolonne);
     
        /*Tableau contenant les lignes de recherche de pivot encore valable
        initialiser à 1,  dès qu'une ligne et colonne sera mobilisé par un pivot
        les tableaux prendrons la valeur 0 aux coordonnées correspondante aux pivot*/
     
     
        int *iPivotpossible = malloc(M->nbreligne*sizeof(int));
     
        int *jPivotpossible = malloc(M->nbrecolonne*sizeof(int));
     
        //Tableaux de coordonnées d'échange de ligne
     
        int *iechange = malloc (M->nbreligne*sizeof(int));
        int *jechange = malloc (M->nbrecolonne*sizeof(int));
     
        //On verifie que tout les pointeurs sont différents de NULL
     
        if (Mb != NULL && Ib != NULL && I != NULL && iPivotpossible != NULL && jPivotpossible != NULL && iechange != NULL && jechange != NULL)
        {
     
        //Initialisation des tableau à la valeur 1
     
        for (i = 0; i < M->nbreligne; i++)
        {
            iPivotpossible[i] = 1;
        }
     
        for (i = 0; i < M->nbrecolonne; i++)
        {
            jPivotpossible[i] = 1;
        }
     
        //Initialisation de la matrice identité
     
        for (i = 0; i < M->nbreligne; i++)
        {
            for(j = 0; j < M->nbreligne; j++)
            {
                if (i != j)
                {
                    I->matrice[i][j] = 0;
                }
                else
                {
                    I->matrice[i][j] = 1;
                }
            }
        }
     
     
        //Début de l'inversion de la matrice
     
        /*Etape 1 : Recherche du pivot, en choisissant la valeur la plus grande
        parmis les valeurs permise restantes*/
     
        for (n = 0; n < M->nbreligne; n++) //Le nombre d'itterration est toujours <= à la dimension de la matrice
        {
            printf("\n\nn = %d",n);
            printf("\n"); //print de controle de l'iteration en cours
     
            if (MatriceNonInversible != 1)
            {
     
                for (k = 0; k < M->nbreligne; k++) //On parcourt le tableau des coordonnées i des pivots restant
                {
                    for (l = 0; l < M->nbrecolonne; l++) //On parcourt le tableau des coordonnées j des pivots restant
                    {
     
                        //Condition d'entrée dans la boucle : coordonnées possible pour le pivot
     
                        if (iPivotpossible[k] != 0 && jPivotpossible[l] != 0)
                        {
                            /*Comparaison d'une valeur absolu possible avec la valeur absolu
                            du pivot déjà en mémoire, si plus grand la valeur devient le pivot*/
     
                            if (fabs(M->matrice[k][l]) > fabs(Pivot))
                            {
                                Pivot = M->matrice[k][l];
                                cPi = k; //On garde en mémoire la valeur des coordonnées du dernier pivot trouvé
                                cPj = l;
                            }
                        }
                    }
                }
     
                    if (Pivot > LimiteMin && Pivot < LimiteMax)
     
                    /*Condition de non inversibilité de la matrice si le
                    pivotmax est nul alors on ne peu pas inverser la matrice*/
                    {
                        MatriceNonInversible = 1;
     
                        //Le programme doit se terminer ici on libère la mémoire
     
                        DetruireMatrice(M);
                        DetruireMatrice(Mb);
                        DetruireMatrice(I);
                        DetruireMatrice(Ib);
     
                        free(iPivotpossible);
                        free(jPivotpossible);
                        free(iechange);
                        free(jechange);
     
                        Ib = NULL;
                    }
     
                    else
                    {
     
                        iPivotpossible[cPi] = 0;//On remplace la valeur 1 par 0 à la coordonée i
                        jPivotpossible[cPj] = 0;//On remplace la valaur 1 par 0 à la coordonée j
                        printf("\nPivot = %f",Pivot);//print de controle des pivots trouvés
                        Pivot = 0;//On réinitialise le pivot pour l'iteration n suivante
     
                        //Etape 2 : Début de l'inversion de la matrice
     
                        for (i = 0; i < M->nbreligne; i++)//On parcour les éléments de matrices
                        {
                            C = (M->matrice[i][cPj])/(M->matrice[cPi][cPj]);/*On rentre le cooeficient lié au pivot qui permetent
                                            de mettre les autres valeurs de la même colonne à 0*/
     
                            printf("\nC = %f", C);//print de controle
     
     
                            for (j = 0; j < M->nbrecolonne; j++)//On parcour en j
                            {
                                if (i != cPi)//Pour les lignes différentes de la ligne du pivot
                                {
     
                                    M->matrice[i][j] = M->matrice[i][j] - C*(M->matrice[cPi][j]);/*On effectue ces transformation pour amener les
                                                                                        autres nombres de la colone du pivot à 0*/
                                    I->matrice[i][j] = I->matrice[i][j] - C*(I->matrice[cPi][j]);/*Même opérations sur la matrice identité*/
     
                                }
                            }
                        }
                    }
            }
        }//ici nous sortons de la boucle lié à n, les ittérations sont toutes faites
     
     
     
     
    if (MatriceNonInversible != 1)
    {
     
        //Etape 3 : On remet les lignes dans le bon ordre, pour cela on les places dans de nouvelles matrices
     
        //On commence par remplacer les valeurs très proche de 0 dût au quelques résidu des dévisions par 0
     
        for (i = 0; i < M->nbreligne; i++)
        {
            for (j = 0; j < M->nbreligne; j++)
            {
                if (M->matrice[i][j] > LimiteMin && M->matrice[i][j] < LimiteMax)
                    {
                        M->matrice[i][j] = 0;
                    }
            }
        }
     
        /*On cherche les valeurs non nuls, grace à leurs coordonées de colonne j on les replace au bonne endroit
        dans une nouvelle matrice c'est à dire à la coordonée jj, on en profite pour ranger les coordonnés
        de lignes et de colonnes dans deux tableaux, Ces tableaux nous permetterons de remetre la matrice I
        dans l'ordres :
        Exemple : iechange[i] = 1
                  jechange[i] = 2
        alors cela signifie que la ligne 1 de Is dois se trouver en réalité à la ligne 2.*/
     
        for (i = 0; i < M->nbreligne; i++)
        {
            for (j = 0; j < M->nbreligne; j++)
            {
                if (M->matrice[i][j] != 0)
                {
                    Mb->matrice[j][j] = M->matrice[i][j];
                    iechange[i] = i;
                    jechange[i] = j;
                }
            }
        }
     
     
     
        /*On effectue les changements de ligne sur la matrice I*/
     
        for (g = 0; g < M->nbreligne; g++)
        {
            for (j = 0; j < M->nbrecolonne; j++)
            {
                Ib->matrice[jechange[g]][j] = I->matrice[iechange[g]][j];
            }
        }
     
     
        /*On divise chaque ligne de Ib pas l'unique élément non nul de Mb de la même ligne
        on obtient donc la matrice inverse de M dans Ib*/
     
        for (i = 0; i < Ib->nbreligne; i++)
        {
            for (j = 0; j < Ib->nbrecolonne; j++)
            {
                Ib->matrice[i][j] = Ib->matrice[i][j]/(Mb->matrice[i][i]);
            }
        }
     
     
     
     
     
     
    //On libère toute la mémoire alloué
     
    DetruireMatrice(M);
    DetruireMatrice(Mb);
    DetruireMatrice(I);
     
    free(iPivotpossible);
     
    free(jPivotpossible);
     
    free(iechange);
     
    free(jechange);
    }
     
     
        }
     
    return Ib;
     
    }
    Je suis encore en phase de test, car j'ai eu pas mal de surprise avec cette fonction, mais je crois que cette fois elle est complète et fonctionne.

  19. #39
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2010
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2010
    Messages : 42
    Points : 21
    Points
    21
    Par défaut
    Bonjour,

    J'ai corrigé certaine erreurs de la fonction (notamment dans le cas d'une matrice non inversible), supprimé les print inutiles, et je l'ai remis en forme, je pense que cette fois elle fonctionne.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
     
    #include "Fonctions_de_base_matrice.h"
    #include "Inversion_matrice_Methode_Gauss.h"
     
    #define LimiteMax 1e-10 //define à modifier en fonction des nombres traité dans la matrice si ceux ci très petit
    #define LimiteMin -1e-10
     
     
     
     
    /*-------------------------------------------------------------------------------------
      Fonction d'inversion d'une matrice de dimensions quelconque par la methode de Gauss
    --------------------------------------------------------------------------------------*/
     
    struct Matrice *Inverse(struct Matrice *matrice)
    {
        int n, i, j, k , l, g, cPi = 0, cPj = 0, MatriceNonInversible = 0;
        double Pivot = 0.0, C;
     
        //Allocation dynamique pour les deux matrices Mb et Ib ainsi que pour les differents tableaux de coordonnées
     
        Matrice *Mb, *Ib = NULL, *I, *M;
     
        M = CreerMatrice(matrice->nbreligne,matrice->nbrecolonne);
     
        /*On copie la matrice "matrice" entrée en paramètre dans une matrice M pour pouvoir conserver notre
        matrice de base*/
     
        for (i = 0; i < matrice->nbreligne; i++)
        {
            for (j = 0; j < matrice->nbrecolonne; j++)
            {
                M->matrice[i][j] = matrice->matrice[i][j];
            }
        }
     
        //Allocation pour les autres matrice dont nous aurons besoin
     
        Mb = CreerMatrice(M->nbreligne,M->nbrecolonne);
        Ib = CreerMatrice(M->nbreligne,M->nbrecolonne);
        I = CreerMatrice(M->nbreligne,M->nbrecolonne);
     
        /*Tableau contenant les lignes de recherche de pivot encore valable
        initialisé à 1,  dès qu'une ligne et colonne sera mobilisé par un pivot
        les tableaux prendrons la valeur 0 aux coordonnées correspondante aux pivot*/
     
     
        int *iPivotpossible = malloc(M->nbreligne*sizeof(int));
     
        int *jPivotpossible = malloc(M->nbrecolonne*sizeof(int));
     
        //Tableaux de coordonnées d'échange de ligne
     
        int *iechange = malloc (M->nbreligne*sizeof(int));
        int *jechange = malloc (M->nbrecolonne*sizeof(int));
     
        //On verifie que tout les pointeurs sont différents de NULL
     
        if (Mb != NULL && Ib != NULL && I != NULL && iPivotpossible != NULL && jPivotpossible != NULL && iechange != NULL && jechange != NULL)
        {
     
            //Initialisation des tableau à la valeur 1
     
            for (i = 0; i < M->nbreligne; i++)
            {
                iPivotpossible[i] = 1;
            }
     
            for (i = 0; i < M->nbrecolonne; i++)
            {
                jPivotpossible[i] = 1;
            }
     
            //Initialisation de la matrice identité
     
            for (i = 0; i < M->nbreligne; i++)
            {
                for(j = 0; j < M->nbreligne; j++)
                {
                    if (i != j)
                    {
                        I->matrice[i][j] = 0;
                    }
                    else
                    {
                        I->matrice[i][j] = 1;
                    }
                }
            }
     
     
            //Début de l'inversion de la matrice
     
            /*Etape 1 : Recherche du pivot, en choisissant la valeur la plus grande
            parmis les valeurs permise restantes*/
     
            for (n = 0; n < M->nbreligne; n++) //Le nombre d'itterration est toujours <= à la dimension de la matrice
            {
                if (MatriceNonInversible != 1)
                {
     
                    for (k = 0; k < M->nbreligne; k++) //On parcourt le tableau des coordonnées i des pivots restant
                    {
                        for (l = 0; l < M->nbrecolonne; l++) //On parcourt le tableau des coordonnées j des pivots restant
                        {
     
                            //Condition d'entrée dans la boucle : coordonnées possible pour le pivot
     
                            if (iPivotpossible[k] != 0 && jPivotpossible[l] != 0)
                            {
                                /*Comparaison d'une valeur absolu possible avec la valeur absolu
                                du pivot déjà en mémoire, si plus grand la valeur devient le pivot*/
     
                                if (fabs(M->matrice[k][l]) > fabs(Pivot))
                                {
                                    Pivot = M->matrice[k][l];
                                    cPi = k; //On garde en mémoire la valeur des coordonnées du dernier pivot trouvé
                                    cPj = l;
                                }
                            }
                        }
                    }
     
                        if (Pivot > LimiteMin && Pivot < LimiteMax)
     
                        /*Condition de non inversibilité de la matrice si le
                        pivotmax est nul alors on ne peu pas inverser la matrice*/
                        {
                            MatriceNonInversible = 1;
     
                            //On suprime la matrice Ib
     
                            DetruireMatrice(Ib);
                            Ib = NULL;
                        }
     
                        else
                        {
                            iPivotpossible[cPi] = 0;//On remplace la valeur 1 par 0 à la coordonée i
                            jPivotpossible[cPj] = 0;//On remplace la valaur 1 par 0 à la coordonée j
                            Pivot = 0;//On réinitialise le pivot pour l'iteration n suivante
     
                            //Etape 2 : Début de l'inversion de la matrice
     
                            for (i = 0; i < M->nbreligne; i++)//On parcour les éléments de matrices
                            {
                                C = (M->matrice[i][cPj])/(M->matrice[cPi][cPj]);/*On rentre le cooeficient lié au pivot qui permetent
                                                                                de mettre les autres valeurs de la même colonne à 0*/
     
                                for (j = 0; j < M->nbrecolonne; j++)//On parcour en j
                                {
                                    if (i != cPi)//Pour les lignes différentes de la ligne du pivot
                                    {
     
                                        M->matrice[i][j] = M->matrice[i][j] - C*(M->matrice[cPi][j]);/*On effectue ces transformation pour amener les
                                                                                                        autres nombres de la colone du pivot à 0*/
                                        I->matrice[i][j] = I->matrice[i][j] - C*(I->matrice[cPi][j]);/*Même opérations sur la matrice identité*/
     
                                    }
                                }
                            }
                        }
     
                }
     
            }//ici nous sortons de la boucle lié à n, les ittérations sont toutes faites
     
     
            if (MatriceNonInversible != 1)
            {
     
                //Etape 3 : On remet les lignes dans le bon ordre, pour cela on les places dans de nouvelles matrices
     
                //On commence par remplacer les valeurs très proche de 0 dût au quelques résidu des dévisions par 0
     
                for (i = 0; i < M->nbreligne; i++)
                {
                    for (j = 0; j < M->nbreligne; j++)
                    {
                        if (M->matrice[i][j] > LimiteMin && M->matrice[i][j] < LimiteMax)
                        {
                            M->matrice[i][j] = 0;
                        }
                    }
                }
     
                /*On cherche les valeurs non nuls, grace à leurs coordonées de colonne j on les replace au bonne endroit
                dans une nouvelle matrice c'est à dire à la coordonée jj, on en profite pour ranger les coordonnés
                de lignes et de colonnes dans deux tableaux, Ces tableaux nous permetterons de remetre la matrice I
                dans l'ordres :
                Exemple : iechange[i] = 1
                          jechange[i] = 2
                alors cela signifie que la ligne 1 de Is dois se trouver en réalité à la ligne 2.*/
     
                for (i = 0; i < M->nbreligne; i++)
                {
                    for (j = 0; j < M->nbreligne; j++)
                    {
                        if (M->matrice[i][j] != 0)
                        {
                            Mb->matrice[j][j] = M->matrice[i][j];
                            iechange[i] = i;
                            jechange[i] = j;
                        }
                    }
                }
     
     
     
                /*On effectue les changements de ligne sur la matrice I*/
     
                for (g = 0; g < M->nbreligne; g++)
                {
                    for (j = 0; j < M->nbrecolonne; j++)
                    {
                        Ib->matrice[jechange[g]][j] = I->matrice[iechange[g]][j];
                    }
                }
     
     
                /*On divise chaque ligne de Ib pas l'unique élément non nul de Mb de la même ligne
                on obtient donc la matrice inverse de M dans Ib*/
     
                for (i = 0; i < Ib->nbreligne; i++)
                {
                    for (j = 0; j < Ib->nbrecolonne; j++)
                    {
                        Ib->matrice[i][j] = Ib->matrice[i][j]/(Mb->matrice[i][i]);
                    }
                }
            }
     
        }
     
        else
        {
            DetruireMatrice(Ib);
            Ib = NULL;
        }
     
        //On libère toute la mémoire alloué
     
        DetruireMatrice(M);
        DetruireMatrice(Mb);
        DetruireMatrice(I);
     
        free(iPivotpossible);
        free(jPivotpossible);
        free(iechange);
        free(jechange);
     
     
    return Ib;
     
    }
    Si il y a des commentaires pour améliorer je suis à l'écoute

  20. #40
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Bonjour,

    tu n'as pas besoin d'inverser ta matrice et il ne faut surtout pas le faire parce que c'est trop coûteux en mémoire et en temps de calcul.
    C'est de plus numériquement pas toujours très stable.

    Dans la formulation matricielle de ton problème aux moindres carrés, l'inverse inv(A) de ta matrice A doit être multipliée par un vecteur v.
    Pour calculer
    w = inv(A)*v,
    on n'inverse jamais A.
    Dans ton cas, tu calcules uniquement la factorisation LU de A (A=LU), et tu résous les deux systèmes triangulaires suivants et successivement :
    Ly = v
    Uw = y
    A priori, ta matrice A est symétrique définie positive (si ton problème est bien posé, elle s'exprime comme le produit d'une matrice inversible et de sa transposée) et tu peux gagner en temps, en mémoire et en précision en calculant la factorisation de Cholesky de A plutôt que la factorisation LU par le pivot de Gauss.
    En particulier, tu n'as plus besoin de faire du pivotage partiel (aucun pivot nul).
    Dans ce cas, A=L*L^T où L est une matrice triangulaire inférieure, et tu résous
    Ly = v
    L^Tw = y
    Note que tu n'as pas besoin de calculer la transposée de L, il suffit d'adapter ton code de remontée de système triangulaire.

Discussions similaires

  1. [Débutant] idée pour améliorer mon code ?
    Par Imène_23 dans le forum MATLAB
    Réponses: 7
    Dernier message: 27/08/2011, 23h54
  2. avis pour améliorer mon cv
    Par Nath_k dans le forum CV
    Réponses: 4
    Dernier message: 20/09/2009, 12h45
  3. Réponses: 30
    Dernier message: 05/08/2009, 19h25
  4. [CV] Avis pour améliorer mon cv
    Par lapanne dans le forum CV
    Réponses: 7
    Dernier message: 17/10/2007, 15h04
  5. Réponses: 4
    Dernier message: 26/04/2006, 14h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo