EMdrive énergie cinétique VS énergie consommée

dedalusman Messages postés 4 Date d'inscription vendredi 5 mars 2010 Statut Membre Dernière intervention 1 juin 2016 - 31 mai 2016 à 17:30
dedalusman Messages postés 4 Date d'inscription vendredi 5 mars 2010 Statut Membre Dernière intervention 1 juin 2016 - 1 juin 2016 à 22:01
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/101502-emdrive-energie-cinetique-vs-energie-consommee

dedalusman Messages postés 4 Date d'inscription vendredi 5 mars 2010 Statut Membre Dernière intervention 1 juin 2016
1 juin 2016 à 22:01
Bien pour le using namespace, je ne savait pas!
Merci encore.
dedalusman Messages postés 4 Date d'inscription vendredi 5 mars 2010 Statut Membre Dernière intervention 1 juin 2016
1 juin 2016 à 09:16
Merci pour le code, il va falloir étudier tout cela.
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
Modifié par cptpingu le 31/05/2016 à 23:53
Bonjour.

La finalité du code est intéressante, mais la technique/design de code est améliorable. On sent que tu viens du C, et que tu te mets au C++, et tu commets quelques maladresses classiques.

Quelques conseils/critiques:
  • Évite les using namespace, voir: http://0217021.free.fr/portfolio/axel.berardino/articles/bon-usage-using-namespace
  • Les typedef partent d'une bonne intention, mais ils ne sont pas nécessaires. D'une part parce qu'au final, seul le type double est utilisée, d'autre part, car ces redéfinitions existent déjà dans <cstdint> (je t'invite à jeter un coup d'oeil, tu y trouveras uint64_t, uint32_t, etc...).
  • Tous les includes en *.h ne sont pas nécessaires en C++. On préfère généralement les versions préfixées par "c" (cstring, cmath, etc...). De plus, on peut s'en passer (voir proposition de correction ci-dessous).
  • L'enum "type_reponse" n'est pas nécessaire. C'est au final une émulation d'un booléen.
  • Quand tu nommes une classe, inutile de préfixer par "class_", on sait déjà que c'en est une :). Idem pour "obj_". En C++, on met par convention une majuscule aux classes.
  • Les attributs d'une classe sont généralement préfixées par "_" pour les différencier de variables locales.
  • Plutôt que de répéter le même motif partout (copier-coller), il est préférable de factoriser le code. Par exemple, les fonctions de demande de valeur peuvent toute être écrite en une seule fonction générique.
  • Il faut "protéger" tes std::cin ! Si je mets "coucou" comme valeur, ton programme va boucler infiniment car tu ne détectes pas l'entrée d'un mauvais type (voir genericAsk ci-dessous).
  • Quand du code n'a pas vocation a être exporté ailleurs, on le met dans un namespace anonyme.
  • Préfère les listes d'initialisation plutôt que d'affecter des valeurs dans le corps du constructeur.
  • Au niveau design, il faut séparer le calcul et l'affichage, qui sont deux tâches distinctes.
  • Une méthode qui n'a pas vocation à modifier les attributs de la classe doit être marquée "const".
  • Plutôt que de faire une méthode "calcul" (qui porte mal son nom car elle est censée uniquement calculer et non afficher), on préférera fournir à notre classe le moyen d'être affichée comme un vrai type via "operator<<".
  • Au lieu de faire plein de std::cout, chaîne-les ! Ça t'évite la création de plein d'objets std::cout pour rien (std::cout est une classe !). Remarque aussi que "cou" "cou" et "coucou" en C et en C++ c'est pareil (le compilateur concatène les constantes). Dans la même optique, préfère écrire "\ntoto" plutôt que "\n" << "toto", ce qui t'évite un appel de fonction pour rien (le "<<" est en fait une fonction, le compilateur transforme ça en: operator<<(operator(out, "\n"), "toto").
  • Évite les magic number. C'est-à-dire les nombres compliquées qui sortent de nulle part (je pense à 31536000 et à 299792458 que j'aurais remplacé par des constantes).


Voici une proposition de réécriture:
#include <iostream>
#include <string>
#include <limits>

namespace
{
  const double LIGHT_SPEED = 299792458;
  const double YEAR = 31536000;

  double genericAsk(const std::string& msg,
            const std::string& err_msg,
            double min, double max)
  {
    bool valid = true;
    double value = 0;

    do
    {
      valid = true;
      while (std::cout << '\n' << msg && !(std::cin >> value))
      {
        std::cin.clear(); // Clear bad input flag
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Discard input
        std::cout << "Invalid input; please re-enter.\n";
      }

      if (value < min || value > max)
      {
        std::cout << "\nATTENTION\n" << err_msg;
        valid = false;
      }
    }
    while (!valid);

    return value;
  }

  class EMDrive
  {
  public:
    EMDrive();
    void askMasse();
    void askPower();
    void askPouss();
    void compute();
    void print(std::ostream& out) const;

  private:
    double _mas_emd;
    double _ene_emd;
    double _pou_emd;
    double _temps;
    double _vitesse;
    double _distance;
    double _energie_cinetique;
    double _energie_consommee;
  };

  EMDrive::EMDrive()
    : _mas_emd(100), // Masse de 100 kg
      _ene_emd(300), // Consommation de 300 watt
      _pou_emd(0.01) // Poussee de 0.01 Newton
  {
    compute(); // Calcul par défaut
  }

  void EMDrive::askMasse()
  {
    _mas_emd = genericAsk("Masse de l'emdrive en kg [1;1000] => ",
              "La masse doit etre entre [1 et 1000] kg",
              1, 1000);
  }

  void EMDrive::askPower()
  {
    _ene_emd = genericAsk("Puissance de l'emdrive en watt [10;10000] => ",
              "la puissance doit etre entre [10 et 10000] watt",
              10, 10000);
  }

  void EMDrive::askPouss()
  {
    _pou_emd = genericAsk("Poussee de l'emdrive en newton [0.000001;100] => ",
              "La poussee doit etre entre [0.000001 et 100] newton",
              0.000001, 100);
  }

  void EMDrive::compute()
  {
    _temps = (2 * _mas_emd * _ene_emd) / (_pou_emd * _pou_emd);
    _vitesse = (_pou_emd / _mas_emd) * _temps;
    _distance = 0.5 * (_pou_emd / _mas_emd) * _temps * _temps;
    _energie_cinetique = 0.5 * (_pou_emd * _temps * _pou_emd * _temps) / _mas_emd;
    _energie_consommee = _ene_emd * _temps;
  }

  void EMDrive::print(std::ostream& out) const
  {
    out <<
      "\n--------------------------------------------------------------"
      "\n*** Au-dela de ce temps, E. cinetique > E. consommee ***"
    << "\nTemps en seconde  = " << _temps
    << "\nTemps en minute   = " << _temps / 60.0
    << "\nTemps en heure    = " << _temps / 3600.0
    << "\nTemps en jour     = " << _temps / 86400.0
    << "\nTemps en annee    = " << _temps / YEAR

    << "\n\nVitesse en m/s    = " << _vitesse
    << "\nVitesse en km/s   = " << _vitesse / 1000.0

    << "\n\nDistance en m     = " << _distance
    << "\nDistance en km    = " << _distance / 1000.0
    << "\nDistance en s.Lu  = " << _distance / LIGHT_SPEED

    << "\n\nEnergie cinetique en joule   = " << _energie_cinetique
    << "\nEnergie cinetique en K.joule = " << _energie_cinetique / 1000.0
    << "\nEnergie cinetique en M.joule = " << _energie_cinetique / 1000000.0
    << "\nEnergie cinetique en G.joule = " << _energie_cinetique / 1000000000.0

    << "\n\nEnergie consommee en joule   = " << _energie_consommee
    << "\nEnergie consommee en K.joule = " << _energie_consommee / 1000.0
    << "\nEnergie consommee en M.joule = " << _energie_consommee / 1000000.0
    << "\nEnergie consommee en G.joule = " << _energie_consommee / 1000000000.0
    << "\n--------------------------------------------------------------";
  }

  std::ostream& operator<<(std::ostream& out, const EMDrive& emdrive)
  {
    emdrive.print(out);
    return out;
  }
} // namespace

int main()
{
  EMDrive emdrive;

  do
  {
    emdrive.askMasse();
    emdrive.askPower();
    emdrive.askPouss();
    emdrive.compute();

    std::cout << emdrive << std::endl;
  }
  while (genericAsk("Voulez-vous recommencer (0 c'est non, autre c'est oui) => ",
            "Nombre invalide!", 0, std::numeric_limits<double>::max()) != 0);

  return 0;
}
Rejoignez-nous