Partage
  • Partager sur Facebook
  • Partager sur Twitter

Cast int

Incompréhension sur le cast int

Sujet résolu
    3 juillet 2019 à 12:10:26

    Bonjour chers développeurs,

    J'aimerais savoir pourquoi j'obtiens ces résultats différents sachant avant de caste la division tombe pile sur un entier 702, un peu bizarre quand même.

    // Example program
    #include <iostream>
    using namespace std;
    
    
    int main()
    {
        cout<<(45.7844-30.2)/0.0222<<endl;
        cout<<(int)((45.7844-30.2)/0.0222)<<endl;
        //cout<<round((45.7844-30.2)/0.0222)<<endl;
    }
    

    Voici les sorties 

    Merci par avance,



    -
    Edité par madj_rek 3 juillet 2019 à 14:21:48

    • Partager sur Facebook
    • Partager sur Twitter
      3 juillet 2019 à 13:55:14

      Salut,

      C'est normal, car lorsque tu fais un "cast à la barbare", la partie décimale et les règles d'arrondis sont purement et simplement ignorées.

      Manque de bol, tu travailles avec des valeurs réelles,représentée sous la forme scientifique (mantisse + exposant), qui sont peut-être impossible à représenter de manière absolument précise en binaire. Si bien que la représentation du résultat correspond peut-être à  quelque chose comme 7.019999998 e-3 au lieu de correspondre comme de juste à 7.02 e-3.

      Si les règles d'arrondis avaient été respectées, la valeur affichée aurait forcément été correcte; mais, du fait de ton cast à la barbare et de son fonctionnement propre, la partie correspondant à 9999998 a "tout simplement" été ignorée, et les règles d'arrondis n'ont pas été respectées.

      Notes que c'est un problème récurrent de la conversion de la base 10 (que l'on est habitué à  utiliser en tant qu'humain) vers la base 2 (qui est la seule réellement manipulable par le processeur) et inversement : dans certains cas, il est purement et simplement impossible de représenter en base 2 des valeurs pourtant finies en base 10 :'(

      Notes enfin que le cast à la barbare tel que tu le fait une pratique très largement déconseillée en C++.

      Et, pour terminer, voici trois conseils qui n'ont rien à voir avec ton problème:

      1- veilles toujours à n'inclure que les fichiers d'en-tête dont tu as strictement besoin : <string> n'a absolument aucun intérêt d'être inclus (et, <cmath> non plus d'ailleurs, surtout au vu du conseil qui suit)

      2- ne laisses pas trainer du code "désactivé" parce que commenté: cela t'éviteras bien des soucis et des questions par la suite en simplifiant la lecture, car

      • tu risque de ne pas te rendre compte "tout de suite" qu'un instruction est commentée, et donc, de te demander pourquoi elle n'est pas exécutée
      • tu risque de te demander pourquoi cette instruction est commentée, et si tu ne dois pas la dé commenter

      3- On n'utilise JAMAIS la directive using namespace std; .  Les raisons et la manière de faire ont été expliquée en long en large et en travers à de nombreuses reprises sur le forum, je te laisserai donc faire une petite recherche à ce sujet ;)

      • Partager sur Facebook
      • Partager sur Twitter
      Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
        3 juillet 2019 à 14:09:30

        #include <iostream>
        #include <iomanip>
        
        int main()
        {
            std::cout << std::setprecision(16) << (45.7844-30.2)/0.0222 << std::endl;
            std::cout << static_cast<int>((45.7844-30.2)/0.0222) << std::endl;
        }
        • Partager sur Facebook
        • Partager sur Twitter
          3 juillet 2019 à 14:20:50

          koala01 a écrit:

          Salut,

          C'est normal, car lorsque tu fais un "cast à la barbare", la partie décimale et les règles d'arrondis sont purement et simplement ignorées.

          Manque de bol, tu travailles avec des valeurs réelles,représentée sous la forme scientifique (mantisse + exposant), qui sont peut-être impossible à représenter de manière absolument précise en binaire. Si bien que la représentation du résultat correspond peut-être à  quelque chose comme 7.019999998 e-3 au lieu de correspondre comme de juste à 7.02 e-3.

          Si les règles d'arrondis avaient été respectées, la valeur affichée aurait forcément été correcte; mais, du fait de ton cast à la barbare et de son fonctionnement propre, la partie correspondant à 9999998 a "tout simplement" été ignorée, et les règles d'arrondis n'ont pas été respectées.

          Notes que c'est un problème récurrent de la conversion de la base 10 (que l'on est habitué à  utiliser en tant qu'humain) vers la base 2 (qui est la seule réellement manipulable par le processeur) et inversement : dans certains cas, il est purement et simplement impossible de représenter en base 2 des valeurs pourtant finies en base 10 :'(

          Notes enfin que le cast à la barbare tel que tu le fait une pratique très largement déconseillée en C++.

          Et, pour terminer, voici trois conseils qui n'ont rien à voir avec ton problème:

          1- veilles toujours à n'inclure que les fichiers d'en-tête dont tu as strictement besoin : <string> n'a absolument aucun intérêt d'être inclus (et, <cmath> non plus d'ailleurs, surtout au vu du conseil qui suit)

          2- ne laisses pas trainer du code "désactivé" parce que commenté: cela t'éviteras bien des soucis et des questions par la suite en simplifiant la lecture, car

          • tu risque de ne pas te rendre compte "tout de suite" qu'un instruction est commentée, et donc, de te demander pourquoi elle n'est pas exécutée
          • tu risque de te demander pourquoi cette instruction est commentée, et si tu ne dois pas la dé commenter

          3- On n'utilise JAMAIS la directive using namespace std; .  Les raisons et la manière de faire ont été expliquée en long en large et en travers à de nombreuses reprises sur le forum, je te laisserai donc faire une petite recherche à ce sujet ;)

          1- Merci pour ton comment, en effet avant de poster ce message dans le forum j'ai procédé comme suit : avant de caster en int (peut-être pas nécessaire finalement) int, j'ai utilisé la fonction round qui permet d'arrondir pour avoir exactement les même valeurs... Tu parles aussi de "cast à la barbare" mais tu proposes pas de solution ou de pistes même si t'as bien décrit le problème

          2-Les fichiers d’entêtes étaient inclus pour d'autres tests que j'ai fait avant c'est pourquoi ils apparaissent mais sinon don't worry.

          3-Ok pour using namespace std, je vais aller vers l'info ;)

          @rouloude

          Cela montre bien le problème ;) la meilleure solution reste à mon avis d'arrondir comme je l'ai mentionné ci-haut :)

          -
          Edité par madj_rek 3 juillet 2019 à 14:37:32

          • Partager sur Facebook
          • Partager sur Twitter
            3 juillet 2019 à 16:01:17

            MadiopLO1 a écrit:

            1- Merci pour ton comment, en effet avant de poster ce message dans le forum j'ai procédé comme suit : avant de caster en int (peut-être pas nécessaire finalement) int, j'ai utilisé la fonction round qui permet d'arrondir pour avoir exactement les même valeurs... Tu parles aussi de "cast à la barbare" mais tu proposes pas de solution ou de pistes même si t'as bien décrit le problème

            Je ne propose aucune alternative pour trois raison majeures:

            1. je ne sais pas ce que tu cherches à faire, donc, j'aurais du mal à te proposer la meilleure solution
            2. la solution la plus simple est toujours la moins compliquée, donc, autant faire au plus simple et éviter le transtypage
            3. et, surtout, le transtypage, quel qu'il soit, n'est jamais qu'un mensonge fait volontairement au compilateur, dans le sens où on l'oblige à manipuler une donnée d'un type donné (un float, dans le cas présent) comme s'il s'agissait d'une donnée d'un type différent (un int, pour l'instant).  Il ne faut donc pas s'étonner si les conséquences de ce mensonge font que l'ordinateur fait n'importe quoi ;)

             Du coup, le meilleur conseil que je puisse te donner, n'est-ce pas encore d'éviter à  tout prix le transtypage ???

            MadiopLO1 a écrit:

            2-Les fichiers d’entêtes étaient inclus pour d'autres tests que j'ai fait avant c'est pourquoi ils apparaissent mais sinon don't worry.

            Oh, je ne m'inquiète pas, mais ca n'empêche:

            • qu'il vaut mieux prendre directement les bonnes habitudes, à savoir, de virer inexorablement tout ce qui n'est pas absolument indispensable à ton code
            • que l'idéal est toujours de partir d'une feuille totalement blanche, même (et surtout ??) quand on ne fait que des tests, pour être sur du résultat obtenu
            • que tu aurais peut-être intérêt à travailler sur de tous nouveau fichiers pour chacun de tes tests, car, qui sait, tu voudras peut-être retourner voir la solution que tu as mise en oeuvre pour l'un de tes tests "plus tard" ;)
            • Partager sur Facebook
            • Partager sur Twitter
            Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
              3 juillet 2019 à 16:39:42

              koala01 a écrit:

              MadiopLO1 a écrit:

              1- Merci pour ton comment, en effet avant de poster ce message dans le forum j'ai procédé comme suit : avant de caster en int (peut-être pas nécessaire finalement) int, j'ai utilisé la fonction round qui permet d'arrondir pour avoir exactement les même valeurs... Tu parles aussi de "cast à la barbare" mais tu proposes pas de solution ou de pistes même si t'as bien décrit le problème

              Je ne propose aucune alternative pour trois raison majeures:

              1. je ne sais pas ce que tu cherches à faire, donc, j'aurais du mal à te proposer la meilleure solution
              2. la solution la plus simple est toujours la moins compliquée, donc, autant faire au plus simple et éviter le transtypage
              3. et, surtout, le transtypage, quel qu'il soit, n'est jamais qu'un mensonge fait volontairement au compilateur, dans le sens où on l'oblige à manipuler une donnée d'un type donné (un float, dans le cas présent) comme s'il s'agissait d'une donnée d'un type différent (un int, pour l'instant).  Il ne faut donc pas s'étonner si les conséquences de ce mensonge font que l'ordinateur fait n'importe quoi ;)

               Du coup, le meilleur conseil que je puisse te donner, n'est-ce pas encore d'éviter à  tout prix le transtypage ???

              Non je pense pas que cela soit la meilleure solution pour calculer l'index maximal d'un segment bien défini (en fait les valeus que j'ai mises en haut cela concerne la multiplication de limite inférieure par la limite supérieure d'un segment du segment [30.2, 45.7844] divisé par le pas 0.0222).

              Je pense la solution consiste à arrondir au lieu de caster en int,

              Merci pour tes précisions et conseils à la prochaine.

              • Partager sur Facebook
              • Partager sur Twitter

              Cast int

              × 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