Partage
  • Partager sur Facebook
  • Partager sur Twitter

Exercice, calculer la moyenne d'un tableau

    9 mai 2013 à 18:47:51

    Bonjour à tous, voilà, je me suis lancé dans l'exercice proposé dans le tuto sur le C qui est de créer une fonction pour calculer la moyenne des valeurs d'un tableau et j'ai donc réalisé ce code : 
    #include <stdio.h>
    #include <stdlib.h>
    
    void affichage(int tableau[], int tailletableau);
    double moyenne(int *ptableau, int tailletableau);
    
    int main(int argc, char *argv[])
    {
        int tableau[5] = {50,60,70,80,90};
        affichage(tableau, 5);
        moyenne(tableau, 5);
        printf("La moyennes des valeurs est : %d\n", moyenne1);
    
        return 0;
    }
    
    void affichage(int tableau[], int tailletableau)
    {
        int i;
        for(i=0; i < tailletableau; i++)
        {
            printf("%d\n", tableau[i]);
        }
        printf("\n");
    }
    
    double moyenne(int *ptableau, int tailletableau)
    {
        int i;
        int p = i + 1;
        double moyenne1 = ptableau[0];
        for(i=0; i < tailletableau; i++)
        {
            moyenne1 = moyenne1 + ptableau[p];
        }
        moyenne1 = moyenne1 / tailletableau;
    
        return moyenne1;
    }
    
    Mais petit problème, le compilateur ne reconnais pas la variable "moyenne1" malgré la valeur retournée en fin de fonction et lorsque je place donc le printf dans la fonction il m'indique une valeur aléatoire comprise en - l'infini et le néant, enfin bref j'ai l'impression qu'il ne réalise pas le calcule des valeurs du tableau mais plutôt leurs adresses

    -
    Edité par BlepBloupBlop 9 mai 2013 à 18:48:56

    • Partager sur Facebook
    • Partager sur Twitter
      9 mai 2013 à 18:52:53

      Yo !

      La variable moyenne1est déclarée dans la fonction moyenne, et est détruite à la fin de celle-ci. Elle n'est donc pas déclarer dans le main ! Sinon, tu peux afficher la moyenne de ton tableau comme ceci :

      printf("La moyennes des valeurs est : %d\n", moyenne(tableau, 5));

      Bonne continuation !

      Edit : Ya aussi un petit problème au niveau de la division, on en parle ici. ;)

      -
      Edité par paraze 9 mai 2013 à 18:53:58

      • Partager sur Facebook
      • Partager sur Twitter
        9 mai 2013 à 18:56:55

        Doctormiller a écrit:

        le compilateur ne reconnais pas la variable "moyenne1"

        Normal, elle n'est pas déclarée !

        Donc il te faut la déclarer puis lui affecter le résultat retourné par la fonction.

        Pour affecter le résultat d'une fonction à une variable on procède de la manière suivante :

        Resultat = LaFonction(eventuel_parametre);
        • Partager sur Facebook
        • Partager sur Twitter
          9 mai 2013 à 19:06:43

          Ok, je pensais qu'une variable retourné dans une fonction était alors défini dans la fonction main() mais effectivement je me suis trompé, autrement pour j'ai lu le tuto et je ne vois toujours pas où se situe ma seconde faute :l

          • Partager sur Facebook
          • Partager sur Twitter
            9 mai 2013 à 19:18:12

            Regarde le passage sur les divisions des nombres flottants (à virgule). ;)

            • Partager sur Facebook
            • Partager sur Twitter
              9 mai 2013 à 19:34:56

              Je comprend pas tout mais c'est au niveau des conversions de type ?

              • Partager sur Facebook
              • Partager sur Twitter
                9 mai 2013 à 19:40:45

                Initialisation des nombres flottants

                Je tiens à retenir votre attention sur la manière d’initialiser les variables flottantes (soit donc de type `floatoudouble`). En fait, ces variables sont faites pour contenir des nombres à virgule. À l’initialisation, il ne faut donc pas se contenter de donner sa valeur, il faut aussi mettre la « virgule ». Sauf que l’on ne met pas une virgule : on met un point.

                const double pi = 3.14;
                

                Cela vient du fait que le C est une invention américaine, et que les anglophones utilisent le point à la place de la virgule, on met un point là où nous autres francophones mettons une virgule.

                Et vous devez impérativement mettre ce point, même si vous voulez stocker un nombre entier dans un `floatou undouble`. Par exemple, vous ne devez pas écrire `double a = 5;maisdouble a = 5.;(certains préfèredouble a = 5.0;`, cela revient au même). Si vous ne le faites pas, vous risquez d’avoir quelques problèmes.

                Voici un petit tableau récapitulatif afin de bien comprendre :

                TypeInitialisation
                char0
                short0
                int0
                long0
                float0.
                double0.
                long double0.

                Division

                La division en informatique est différente de celle en mathématiques. Si je vous dis 15/4, vous en déduisez que le quotient est 3,75. Pourtant, le résultat de celle-ci est 3 en langage C.

                int division = 15 / 4;
                

                Suite à la lecture du chapitre suivant, vous pourrez vérifier cette affirmation en affichant la valeur de cette opération, mais vous n’en êtes pas encore là, et je vous défends de vous y rendre avant la fin de ce chapitre.

                Pour l’ordinateur, le résultat de `15 / 4est bien3`. Pourquoi ? Parce qu’on lui a demandé de faire une division d’entiers (appelée division euclidienne), donc il répond par des entiers. Si l’on veut afficher le résultat complet (à nos yeux), il faut l’indiquer à l’ordinateur. Comment faire ? Essayez de trouver la solution tout seul.

                Un indice ? Pensez aux flottants.

                La solution :

                double division = 15. / 4.;   /* même si pour nous, c’est la même chose que 15 / 4 */
                

                Même si pour nous c’est intuitif, pour l’ordinateur il faut bien préciser si ce sont des entiers ou des flottants.


                Sur ce. :D

                • Partager sur Facebook
                • Partager sur Twitter
                  9 mai 2013 à 19:47:54

                  Oui ok, du coup mon double et divisé par un int, mais je ne peut pas redéfinir la variable avec un simple point ? Si ?

                  • Partager sur Facebook
                  • Partager sur Twitter
                    9 mai 2013 à 20:04:48

                    Les conversions de type

                    La conversion de type est une opération qui consiste à changer le type d’une variable en un autre. Je peux ainsi convertir une variable de type `floaten typeint`, par exemple. Il existe deux types de conversions : les conversions explicites et les conversions implicites.

                    Les conversions explicites

                    Ce sont des conversions voulues et demandées par le programmeur. Elles se déclarent en suivant ce modèle :

                    (<Type>) <Expression>
                    

                    Voici par exemple un code où l’on demande explicitement la conversion d’un `doubleenint`.

                    int a;
                    const double pi = 3.14;
                    
                    a = (int) pi;
                    

                    La valeur de `pireste inchangée, elle vaudra toujours 3.14 dans la suite du programme. Par contre,avaut maintenant 3, puisque le flottant a été converti en entier. Expliciter une conversion peut nous servir quand on veut forcer le résultat d’une opération par exemple. Imaginons que nous voulons faire une division, mais que les deux opérandes soient de typeint`.

                    int a, b;
                    double c;
                    
                    a = 5;
                    b = 9;
                    
                    c = a / b;
                    

                    Vu qu’on fait une division euclidienne, le résultat sera tronqué. Si on veut avoir un résultat avec la partie décimale, il suffit de faire une conversion explicite d’un des deux opérandes en `double` :

                    c = (double) a / b;
                    /* ou */
                    c = a / (double) b;
                    

                    Les conversions implicites

                    Ce sont des conversions que fait le compilateur tout seul, sans que l’on ait demandé quoi que ce soit. En général, ça ne gêne pas le programmeur, mais ça peut parfois être problématique si la conversion n’était pas voulue. Par exemple, si l’on reprend le code précédent, il y aura toujours une conversion.

                    int a;
                    const double pi = 3.14;
                    
                    /* Il y a conversion implicite de double en int, mais rien 
                    n’est précisé, c’est le compilateur qui fait ça de lui-même. */
                    a = pi;
                    

                    Cependant, les conversions amènent parfois à des pertes d’information si l’on n’y prend pas garde.

                    Perte d’information

                    Une perte d’information survient quand on convertit le type d’une variable en un autre type plus petit et que celui-ci ne peut pas contenir la valeur reçue. Si, par exemple, je convertis un `doublede 100 chiffres en unshort`, il y a perte d’information, car le type `short` ne peut pas contenir 100 chiffres. La règle à retenir est la suivante :

                    Si on convertit un type T vers un type S plus petit, il y a perte d’information. Règle des conversions

                    Les conversions, et surtout les conversions implicites qui peuvent être vicieuses, doivent être manipulées avec précaution, au risque de tomber sur des valeurs fausses en cas de perte d’information. Nous découvrirons d’ici quelques chapitres comment connaitre la taille d’un type T pour éviter ces pertes d’information.


                    ^^

                    • Partager sur Facebook
                    • Partager sur Twitter
                      9 mai 2013 à 21:43:03

                      paraze a écrit:

                      Par exemple, vous ne devez pas écrire double a = 5; mais double a = 5.; (certains préfère double a = 5.0;, cela revient au même). Si vous ne le faites pas, vous risquez d’avoir quelques problèmes.

                      Hum, des problèmes? Je ne vois pas lesquels. Ne serait-ce pas une invention?

                      paraze a écrit:

                      La conversion de type est une opération qui consiste à changer le type d’une variable en un autre.

                      Non, le type d'une variable est défini une fois pour toute à la déclaration.

                      La conversion de type est une opération qui consiste à produire une valeur du type demandé à partir d'une autre valeur. Ça n'a rien à voir avec les variables.

                      • Partager sur Facebook
                      • Partager sur Twitter
                        9 mai 2013 à 21:49:10

                        @Marc Mongenet : Pour le premier point, on parlait surtout du fait que pour faire des divisions entre flottant ça risquait de coincer un peu, de ne pas donner le résultat attendu; c'est vrai qu'on devrait un peu nuancer cette partie-là. Le second point a déjà été corrigé, mais en Bêta-Test, la version en ligne est donc incorrecte (c'est pourquoi on est un peu dégoutté du fait qu'on ne puisse pas mettre à jour notre tutoriel, surtout que plusieurs chapitres / ajouts / corrections étaient sur le point de passer en ligne). Bref, j'aurai dû corrigé ce problème là à la main, mais j'avais oublié que l'erreur était encore présente.

                        • Partager sur Facebook
                        • Partager sur Twitter
                          10 mai 2013 à 11:52:37

                          Du coup j'ai changé mon code en ça : 

                          #ifndef MAIN_H_INCLUDED
                          #define MAIN_H_INCLUDED
                          
                          void affichage(int tableau[], int tailletableau);
                          double moyenne(int *ptableau, int tailletableau);
                          
                          void affichage(int tableau[], int tailletableau)
                          {
                              int i;
                              for(i=0; i < tailletableau; i++)
                              {
                                  printf("%d\n", tableau[i]);
                              }
                              printf("\n");
                          }
                          
                          double moyenne(int *ptableau, int tailletableau)
                          {
                              int i;
                              int p = i + 1;
                              double moyenne1 = (double) ptableau[0];
                              for(i=0; i < tailletableau; i++)
                              {
                                  moyenne1 += (double) ptableau[p];
                              }
                              moyenne1 /= (double) tailletableau;
                          
                              return moyenne1;
                          }
                          
                          #endif // MAIN_H_INCLUDED
                          que j'ai d'ailleurs mit dans un .h mais toujours le même problème hélas :/ j'utilise sans doute très mal le "(double)"
                          • Partager sur Facebook
                          • Partager sur Twitter
                            10 mai 2013 à 11:58:00

                            Dans un fichier header, .h on ne met que des déclaration pas de définition !
                            • Partager sur Facebook
                            • Partager sur Twitter
                              10 mai 2013 à 12:02:08

                                  int i;
                                  int p = i + 1;
                              

                              Attention ici, tu utilise la variable i sans l'avoir préalablement utilisée !


                               

                              • Partager sur Facebook
                              • Partager sur Twitter
                                10 mai 2013 à 12:14:30

                                Lucien63 a écrit:

                                Dans un fichier header, .h on ne met que des déclaration pas de définition !


                                C'est à dire ? x)
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  10 mai 2013 à 12:19:51

                                  Ça :

                                  void affichage(int tableau[], int tailletableau);

                                  C'est une déclaration de fonction.

                                  et ça :

                                  void affichage(int tableau[], int tailletableau)
                                  {
                                      int i;
                                      for(i=0; i < tailletableau; i++)
                                      {
                                          printf("%d\n", tableau[i]);
                                      }
                                      printf("\n");
                                  }
                                  

                                  C'est la définition de la même fonction.


                                   

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    10 mai 2013 à 12:49:21

                                    Ok

                                    du coup j'ai séparé mon code comme ça, main.c : 

                                    #include <stdio.h>
                                    #include <stdlib.h>
                                    #include "main.h"
                                    
                                    int main(int argc, char *argv[])
                                    {
                                    
                                        int tableau[5] = {50,60,70,80,90};
                                        affichage(tableau, 5);
                                        moyenne(tableau, 5);
                                        printf("La moyennes des valeurs est : %d\n", moyenne(tableau, 5));
                                    
                                        return 0;
                                    }
                                    
                                    void affichage(int tableau[], int tailletableau)
                                    {
                                        int i;
                                        for(i=0; i < tailletableau; i++)
                                        {
                                            printf("%d\n", tableau[i]);
                                        }
                                        printf("\n");
                                    }
                                    
                                    double moyenne(int *ptableau, int tailletableau)
                                    {
                                        int i;
                                        double moyenne1 = (double) ptableau[0];
                                        for(i=0; i < tailletableau; i++)
                                        {
                                            moyenne1 += (double) ptableau[i+1];
                                        }
                                        moyenne1 /= (double) tailletableau;
                                    
                                        return moyenne1;
                                    }
                                    

                                    Et voici le main.h : 

                                    #ifndef MAIN_H_INCLUDED
                                    #define MAIN_H_INCLUDED
                                    
                                    void affichage(int tableau[], int tailletableau);
                                    double moyenne(int *ptableau, int tailletableau);
                                    
                                    #endif // MAIN_H_INCLUDED
                                    

                                    Mais du coup le compilateur me dis que les fonctions ont déjà été définis et ne compile plus :l

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      10 mai 2013 à 13:19:21

                                      Voici un petit tableau récapitulatif afin de bien comprendre : Type | Initialisation ------------- | ------------- char | '\0' short | 0 int | 0 long | 0l float | 0.f double | 0. long double | 0.lf

                                      Bref, le Sdz ne me permet pas de bien formater le tout mais l'idée est là ...

                                      -
                                      Edité par @che 10 mai 2013 à 13:22:35

                                      • Partager sur Facebook
                                      • Partager sur Twitter

                                      🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.

                                        10 mai 2013 à 13:30:32

                                        Doctormiller a écrit:

                                        Mais du coup le compilateur me dis que les fonctions ont déjà été définis et ne compile plus :l

                                        Pas possible ! tu as bien enregistré le nouveau fichier main.h ?

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          10 mai 2013 à 13:39:08

                                          Lucien63 a écrit:

                                          Doctormiller a écrit:

                                          Mais du coup le compilateur me dis que les fonctions ont déjà été définis et ne compile plus :l

                                          Pas possible ! tu as bien enregistré le nouveau fichier main.h ?

                                          Oui, j'ai relancé code block en enregistrant bien tout et maintenant ça marche. Du coup j’initialise ma variable moyenne1 puis je lui attribut la valeur de ptableau[0] et je compile le tout et j'obtiens 0 maintenant :l

                                          Le code de ma fonction :

                                          double moyenne(int *ptableau, int tailletableau)
                                          {
                                              int i;
                                              double moyenne1 = 0.;
                                              moyenne1 = (double) ptableau[0];
                                              for(i=0; i < tailletableau; i++)
                                              {
                                                  moyenne1 += (double) ptableau[i+1];
                                              }
                                              moyenne1 /= (double) tailletableau;
                                          
                                              return moyenne1;
                                          }
                                          




                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            10 mai 2013 à 13:41:49

                                            Dans la fonction qui calcule la moyenne, ce que tu calcules dans la boucle for est une somme d'éléments de tableau, et non une moyenne.

                                            Il serait donc judicieux d'appeler la variable de calcul somme, et pas moyenne.  C'est important, d'appeler les choses par leur nom.

                                            C'est quand le calcul de la somme est terminé, qu'on retourne la valeur de la moyenne, qui est le quotient de la somme par le nombre d'éléments

                                                  return somme/tailletableau;

                                             Par ailleurs

                                            - tu as un bug d'indice au dernier tour de la boucle, quand i vaut tailletableau-1,

                                            - tu fais des complications inutiles en mélangeant notations indicées et pointeurs

                                            - tes conversions de types sont toutes inutiles.  Il en fallait une au niveau de la division quand tu divisais une somme (dans un int) par le nombre d'éléments, int aussi. Là ce n'est plus le cas.

                                            -
                                            Edité par michelbillaud 10 mai 2013 à 13:50:06

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              10 mai 2013 à 14:05:57

                                              Ok, donc voilà mon code à peu près propre :

                                              double moyenne(int ptableau[], int tailletableau)
                                              {
                                                  int i;
                                                  int somme = 0;
                                                  double moyenne1 = 0.;
                                                  somme = ptableau[0];
                                                  for(i=0; i < tailletableau; i++)
                                                  {
                                                      somme += ptableau[i+1];
                                                  }
                                              
                                                  return somme/tailletableau;
                                              }

                                              Mais j'obtiens toujours 0

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                10 mai 2013 à 14:12:33

                                                Attention ptableau[i+1] au dernier tour de boucle est equivalent à ptableau[5] or cette case du tableau ce trouve en dehors de ton tableau.

                                                Les indice de tableau vont de 0 à N-1

                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  10 mai 2013 à 14:25:53

                                                  Ok, du coup il suffit de remplacer ptableau[i+1] par ptableau[i] ?
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    10 mai 2013 à 14:44:56

                                                    A un détail prés, Oui !

                                                    (Le détail c'est que tu affectes déjà la valeur de la case d'indice 0 à somme avant d'executer la boucle.)

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      10 mai 2013 à 14:47:46

                                                      Attention aussi quand tu fait :

                                                      return somme/tailletableau;

                                                      somme et taille sont des entiers et tu retournes un double.

                                                      L'opération sera exécutée avant la convertion en double !

                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        10 mai 2013 à 14:55:44

                                                        J'ai modifier mon code comme ça :

                                                        double moyenne(int ptableau[], int tailletableau)
                                                        {
                                                            int i;
                                                            int somme = ptableau[0];
                                                            double moyenne1 = 0.;
                                                            for(i=0; i < tailletableau; i++)
                                                            {
                                                                somme += ptableau[i];
                                                            }
                                                        
                                                            return (double) somme/ (double) tailletableau;
                                                        }

                                                        mais toujours un résultat égal à 0

                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          10 mai 2013 à 15:07:02

                                                          Affichage à 0 bizard ?

                                                          Mais oui :

                                                              printf("La moyennes des valeurs est : %d\n", moyenne(tableau, 5));


                                                          Pour afficher un double c'est %f et non pas %d

                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            10 mai 2013 à 15:09:31

                                                            Autrement dans le code de la fonction moyenne, il subsiste deux petite erreurs :

                                                            moyenne1 ne sert à rien vu que tu ne l'utilise pas !

                                                            Et tu additionne deux fois la case ptableau[0] !

                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                              10 mai 2013 à 15:20:57

                                                              Oui j'ai corrigé et le code marche impeccable ! Merci beaucoup, une solution pour réduire le nombre de chiffre significatifs après la virgule ? Je veux en mettre seulement 2
                                                              • Partager sur Facebook
                                                              • Partager sur Twitter

                                                              Exercice, calculer la moyenne d'un tableau

                                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                              • Editeur
                                                              • Markdown