Besoin d'aide pour trouver mon erreur

Besoin d'aide pour trouver mon erreur - C++ - Programmation

Marsh Posté le 26-03-2019 à 11:31:31    

Bonjour,
 
J'apprends à mon rythme à programmer en C++. Pour m'aider, je navigue entre plusieurs sites.
On me propose un exercice dont voici un résumé du sujet:
 
"Une opération de lissage d'une séquence de mesures (des nombres décimaux) consiste à remplacer chaque mesure sauf la première et la dernière, par la moyenne des deux valeurs qui l'entourent.
Par exemple, si l'on part de la séquence de mesures suivantes :
1 3 4 5
On obtient après un lissage :
1 2.5 4 5
Le premier et dernier nombre sont inchangés. Le deuxième nombre est remplacé par la moyenne du 1er et du 3e, soit (1+4)/2 = 2.5
Votre programme doit calculer le nombre minimum de lissages successifs nécessaires pour s'assurer que la valeur absolue de la différence entre deux valeurs successives de la séquence finale obtenue ne dépasse jamais une valeur donnée, diffMax."

 
Ensuite les exigences demandés sur le site pour le programme:
 
Entrée
La première ligne de l'entrée contient un entier : nbMesures.
La deuxième ligne de l'entrée contient un nombre décimal : diffMax.
Chacune des nbMesures lignes suivantes contient une mesure, sous la forme d'un nombre décimal.
 
Sortie
Vous devez afficher un entier sur la sortie : le nombre minimal de lissages nécessaire.

 
Enfin le programme que j'ai écrit:
 

Code :
  1. #include <iostream>
  2. #include <cmath>
  3. using namespace std;
  4. int main ()
  5. {
  6.    int nbMesure, nbLissage =0;
  7.    cin >> nbMesure;
  8.    double diffMax, mesure[nbMesure], difference[nbMesure -1], diffLaPlusGrande = 0;
  9.    cin >> diffMax;
  10.    for (int iMes(0); iMes < nbMesure; iMes++)
  11.       cin >> mesure[iMes];
  12.    do
  13.    {
  14.       for (int i(1); i < nbMesure - 2; i++)   //lissage
  15.       { 
  16.          mesure [i] = (mesure[i-1] + mesure[i+1])/2;
  17.          nbLissage++;
  18.       }
  19.       for (int iDiff (0); iDiff < nbMesure - 1; iDiff++) // calcul diff
  20.       {
  21.          difference [iDiff] = abs (mesure [iDiff] - mesure [iDiff+1]);
  22.          if (difference[iDiff] > diffLaPlusGrande)   // Mémorisation de la plus grande différence
  23.             diffLaPlusGrande = difference [iDiff];     
  24.       }
  25.    }
  26.    while (diffLaPlusGrande >= diffMax);
  27.    cout << nbLissage << endl;
  28. }


 
Quand je fais des tests, suivant les valeurs que je donne, soient il fonctionne, soit il est trop long.
J'ai beau me casser la tête, je ne trouve pas mon erreur...
Je ne vous demande pas de me donner une réponse ou une solution mais simplement de me dire où est mon erreur.
 
Merci d'avance.
Grockes

Reply

Marsh Posté le 26-03-2019 à 11:31:31   

Reply

Marsh Posté le 26-03-2019 à 16:06:43    

Je pense que ligne 15 la condition c'est plutôt i < nbMesure - 1 non?
Sinon tu peux donner quelque valeurs à entrer dans le logiciel pour se rendre compte du problème?

Reply

Marsh Posté le 26-03-2019 à 16:11:38    

La ligne 9 me paraît un peu suspecte dans la déclaration mesure[nbMesure] et difference[nbMesure -1]
 
Faudrait pas faire un truc du genre :
int nbMesure;    
std::cin >> nbMesure;
double *mesure = new double[nbMesure];
:??:
Bon après, ça fait bien longtemps que j'ai pas refait de C++.


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 27-03-2019 à 10:10:30    

Bonjour !  
 
Je pense qu'il y a une erreur d'algorithme, et qu'il faudrait sauvegarder les valeurs "moyennées" dans un autre tableau. J'explique mon point de vue avec le même exemple que l'énoncé :
 
Avant : 1 3 4 5
 
on fait "mesure[1] = (mesure[0] + mesure[2])/2  
->  1 2.5 4 5
 
 On fait "mesure[2] = (mesure[1]+mesure[3])/2
-> 1 2.5 3.75 5 au lieu de 1 2.5 4 5
 
De plus, je suis tout à fait d'accord avec la remarque de rat de combat.
 
Qui plus est, il faudrait remettre à 0 la valeur "diffLaPlusGrande" à chaque étape (dans la boucle "do" ) car si, comme on l'espère, la différence est amenée à baisser (en valeur absolue) à chaque itération, on reste bloqué à la valeur obtenue lors de la première, ce qui correspond au diagnostic : Soit ça va très vite, soit c'est très long, et même plus, car on ne sort jamais.
 
Et, juste pour terminer, le tableau "difference" ne sert à rien, vu qu'on consomme tout de suite la valeur calculée, on pourrait utiliser une variable de type double pour faire le calcul intermédiaire et comparer le résultat au max de ce coup-ci.
 
 
Voilà, avec toutes ces corrections, cela devrait aller mieux :)
 
Bonne continuation !


---------------
On n'est jamais très fort pour ce calcul !
Reply

Marsh Posté le 27-03-2019 à 10:32:40    

Merci pour vos réponses!
 
Je vais faire des essais pour remettre diffLaPlusGrande à zéro à chaque tour. Effectivement, je n'avais pas pensé qu'on veut que la valeur baisse à chaque "lissage".
 
Pour en revenir à la ligne 15, la 1ere et la dernière mesure restent constante donc ça fait bien nbMesure -2.
 
Le lissage se fait avec les anciennes valeurs et ne s'ajuste pas au fur et à mesure... leur exemple est donc juste... Mais faut que je revois ma façon de faire pour voir si je fais comme l'exemple ou comme Farian viens de l'expliquer.
 
En tout cas, encore merci j'ai des pistes d'améliorations!

Reply

Marsh Posté le 27-03-2019 à 13:29:02    

grockes a écrit :

Pour en revenir à la ligne 15, la 1ere et la dernière mesure restent constante donc ça fait bien nbMesure -2.

Tu as une comparaison stricte, du coup il faut -1 pour aller jusqu'à l'avant-dernière valeur qui se trouve en [nbMesure-1-1]. La valeur limite que tu indiques n'est jamais atteinte (comparaison stricte)!

Reply

Marsh Posté le 27-03-2019 à 14:24:21    

J'ai pas testé (je suis au taff) mais a vue de nez, je tenterais un truc de ce genre :  

Code :
  1. #include <iostream>
  2. #include <cmath>
  3. using namespace std;
  4. int main ()
  5. {
  6.   int nbMesure;
  7.   cin >> nbMesure;
  8.  
  9.   double diffMax;
  10.   cin >> diffMax;
  11.  
  12.   double mesure[nbMesure];
  13.   for (int i = 0; i < nbMesure; ++i) {
  14.       cin >> mesure[i];
  15.   }
  16.  
  17.   int diffPlusGrande, nbLissage = 0;
  18.  
  19.   do {
  20.     for (int i = 1; i < nbMesure-1; ++i) {
  21.       mesure [i] = (mesure[i-1] + mesure[i+1])/2;
  22.     }
  23.     ++nbLissage;
  24.    
  25.     diffPlusGrande = 0;
  26.     for (int i = 0; i < nbMesure-1; ++i) {
  27.       if (abs(mesure[i] - mesure [i+1]) >= diffMax) {
  28.         diffPlusGrande = 1;
  29.         break;
  30.       }
  31.     }
  32.   } while (diffPlusGrande);
  33.   cout << nbLissage << endl;
  34.   return(0);
  35. }


 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 27-03-2019 à 16:18:11    

Code élégant, Gilou !
 
Sauf que ma remarque sur l'écrasement des mesures au fur et à mesure du calcul  reste vraie et cela ne correspond pas à l'algorithme tel que décrit dans l'énoncé.
 
Bonne continuation !


---------------
On n'est jamais très fort pour ce calcul !
Reply

Marsh Posté le 27-03-2019 à 17:09:34    

Farian a écrit :

Code élégant, Gilou !

 

Sauf que ma remarque sur l'écrasement des mesures au fur et à mesure du calcul  reste vraie et cela ne correspond pas à l'algorithme tel que décrit dans l'énoncé.

 

Bonne continuation !

Oui, tu as parfaitement raison, j'en rougis de honte :o
J'aurais pas eu l'esprit occupé à déployer un patch en prod, je m'en serais probablement rendu compte.

 

bon ben on va utiliser des temporaires alors pour stocker avant modification et réutilisation alors.

 

do {
    double temp1= mesure[0];
    for (int i = 1; i < nbMesure-1; ++i) {
      double temp2 = mesure[i];
      mesure [i] = (temp1 + mesure[i+1])/2;
      temp1 = temp2;
    }

 

Mais par contre, il y a un pb avec la fonction de lissage: en prenant un facteur 1/2, on peut boucler a l'infini sur une suite constante.
E.G. 1, 3, 4, 5, va boucler au bout de 52 itérations sur 1, 2+1/3, 3+2/3, 5. En effet (1 + 3 + 2/3)/2 = 14/6 = 2+1/3 et (2 + 1/3 + 5)/2 = 22/6 = 3 + 2/3
Si on veut éviter ce phénomène, il faut vérifier que l'on atteint pas une valeur constante. Et comme on a des floats...

 

A+,


Message édité par gilou le 27-03-2019 à 18:27:20

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 28-03-2019 à 13:31:41    

Merci Gilou, je n'avais pas pensé non plus à mettre un Break!
 
Je pense que ta solution des temporaires doit être bonne, mais je vais devoir m'en passer car je ne l'ai pas encore abordé dans les cours que je suis.
Par contre, je vais voir si je trouve des infos là-dessus ça me paraît très intéressant!
 
Je ne vais pas copier ton programme (ou peut-être juste pour le tester) mais il sera source d'inspiration.
 
Et merci aussi aux autres, je n'ai pas encore eu le temps de modifier mon programme, mais j'ai déjà plusieurs pistes pour arriver à mes fins!

Reply

Marsh Posté le 28-03-2019 à 13:31:41   

Reply

Marsh Posté le 29-03-2019 à 11:23:50    

> Je pense que ta solution des temporaires doit être bonne, mais je vais devoir m'en passer car je ne l'ai pas encore abordé dans les cours que je suis.  
Mais il y a rien de spécial la : je définis deux variables ordinaires que j'utilise pour stocker temporairement des valeurs utilisées dans (et susceptibles d'être modifiées par) les calculs.
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed