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

Langage C++ Discussion :

Approximation d'un float


Sujet :

Langage C++

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    52
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 52
    Points : 29
    Points
    29
    Par défaut Approximation d'un float
    Je réalise actuellement un petit programme pour traiter des trames

    J'ai des float, int et string
    Pour les float, je fais face à un problème que je n'arrive pas à résoudre.

    La trame qui m'intéresse avec en gras ce que je prends
    $IIMWV,220.1,R,000.30,N,A

    Voilà ma méthode pour traiter les valeurs que j'ai extrait le 220.1
    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
     
    float WM918::DecapsuleDirectionVent(String DirectionBrute)
    {
            int     Cen,
                    Diz,
                    Uni,
                    Dix;
            float   Resultat=0;
     
            Cen=(VitesseBrute[1] & 0x0f);
            Diz=(VitesseBrute[2] & 0x0f);
            Uni=(VitesseBrute[3] & 0x0f);
            Dix=(VitesseBrute[5] & 0x0f);
     
            Resultat= (Cen*100)+(Diz*10)+Uni+(Dix*0.1);
     
            return Resultat;
    }
    Je devrais récupérer un float = 220.1 alors que je récupère un float = 220,100006103516

    Je ne comprends pas pourquoi même en mettant un Resultat=Resultat-0,000006103516 avant le return je trouve toujours 220,100006103516 !

    Merci d'avance pour vos futurs réponses

  2. #2
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    C'est un problème de représentation binaires des nombres réels. Tu trouveras beaucoup d'information sur cette problèmatique (en particulier What Every Computer Scientist Should Know About Floating-Point Arithmetic). Tu peux tenter de passer aux doubles ou aux représentation à virgule fixe

  3. #3
    Membre éclairé
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Points : 879
    Points
    879
    Par défaut
    Ou bien, étant donné la fonction qui lit les données, il suffit de mettre dans un nombre entier en sachant que cet entier est le flottant représenté fois 10.
    Il suffit ensuite de diviser par 10 si on a absolument besoin de ce flottant.

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    52
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 52
    Points : 29
    Points
    29
    Par défaut
    merci à vous 2 pour vos réponses !

    Je n'avais pas penser à diviser par 10 très bonne idée je vais test !

  5. #5
    Membre éclairé
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Points : 879
    Points
    879
    Par défaut
    Non mais ça ne marchera pas plus, hein.

    C'est juste que 0,000006103516 est l'imprécision minimum que doit comporter ton float.
    Les deux solution sont alors soit de passer par un double, soit d'émuler du fixed point en stockant uniquement le nombre fois dix et en n'utilisant jamais de float.

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Effectivement, ce genre de données se traite bien avec un entier en changeant ton unité de représentation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int WM918::DecapsuleDirectionVent(String VitesseBrute)
    {
            const int Cen=(VitesseBrute[1] & 0x0f);
            const int Diz=(VitesseBrute[2] & 0x0f);
            const int Uni=(VitesseBrute[3] & 0x0f);
            const int Dix=(VitesseBrute[5] & 0x0f);
     
            const int Resultat= (Cen*1000)+(Diz*100)+(Uni*10)+Dix;
     
            return Resultat;
    }
    Pourquoi WM918::DecapsuleDirectionVent(String VitesseBrute) n'accède à aucune variable membre de la classe ? Des fonctions libres avec un espace de nom c'est une solution alternative aux classes à fonctions statiques.

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    52
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 52
    Points : 29
    Points
    29
    Par défaut
    Alors là vous avez complètement perdu

    Je pensais avoir compris tout ce que je faisais mais là j'ai l'impression que je m'emmêle les pinceaux !

    3DArchi je comprends pas ce que tu essayes d'expliquer car DirectionBrute (VitesseBrute) est une variable membre de la classe

    Donc avec un double ça donne ça :
    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
     
    double WM918::DecapsuleDirectionVent(String DirectionBrute)
    {
            int     Cen,
                    Diz,
                    Uni,
                    Dix;
            double   Resultat=0;
     
            Cen=(VitesseBrute[1] & 0x0f);
            Diz=(VitesseBrute[2] & 0x0f);
            Uni=(VitesseBrute[3] & 0x0f);
            Dix=(VitesseBrute[5] & 0x0f);
     
            Resultat= (Cen*100)+(Diz*10)+Uni+(Dix*0.1);
            return Resultat;
    }
    J'obtiens bien 220.1 mais vous ne pensez pas qu'avec un double cela surcharge le programme ?


    EDIT : J'avais fait une erreur au niveau du nom du paramètre mais ça change rien au problème

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Ce que 3Darchi a fait remarquer est qu'une fonction membre qui n'accès à aucune donnée membre ni n'utilise aucune autre fonction membre est étrange.
    Ca n'a rien à faire comme fonction membre, ça n'utilise aucun membre.

    Ou bien il s'agit d'une fonction statique de la classe et tu t'es emmêle ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  9. #9
    Membre éclairé
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Points : 879
    Points
    879
    Par défaut
    Citation Envoyé par Mini-Tyson Voir le message
    Alors là vous avez complètement perdu

    Je pensais avoir compris tout ce que je faisais mais là j'ai l'impression que je m'emmêle les pinceaux !

    3DArchi je comprends pas ce que tu essayes d'expliquer car DirectionBrute (VitesseBrute) est une variable membre de la classe
    DirectionBrute n'est pas une variable membre de la classe utilisée par la fonction, puisqu'elle est passée en paramètre.

    Du coup, tu pourrais sortir cette fonction de la classe, en la mettant dans un namespace impl par exemple.

    Citation Envoyé par Mini-Tyson Voir le message
    Donc avec un double ça donne ça :
    [...]
    J'obtiens bien 220.1 mais vous ne pensez pas qu'avec un double cela surcharge le programme ?
    [...]
    Non. En fait, un double est parfois plus rapide qu'un float, au détriment d'un peu de mémoire, parce que les processeurs sont plus optimisés pour les double.

    Mais la solution avec un entier en retournant la solution en dixièmes de [l'unité que tu avais avant] permettrait une précision absolue.
    Si on savait ce que tu fais ensuite de cet entier, ça nous aiderait.

  10. #10
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    52
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 52
    Points : 29
    Points
    29
    Par défaut
    ah ok merci je ne savais pas !


    En faites je récupères une trame, je la traite pour ne prendre que la partie qui m'intéresse puis je décapsule (donc la fonction posté) pour récupérer la valeur qui m'intéresse et l'attribuer à une variable de ma classe pour pouvoir la partager et ainsi afficher ma valeur sur une IHM sous forme décimale ou traiter par un composant (genre boussole) ! Donc une précision absolue n'est pas vraiment nécessaire ni obligatoire !

    Sinon je ne comprends pas pourquoi vous voulez sortir la fonction de la classe, je suis un peu perdu sur ce point ! Je trouve mon programme plus simple avec une classe unique qui se charge de traiter l'ensemble de la trame ainsi que la décapsulation.

  11. #11
    Membre éclairé
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Points : 879
    Points
    879
    Par défaut
    Si tu n'utilises que pour un affichage, alors à l'affichage tu peux faire quelque chose comme out << (valeur / 10) << '.' << (valeur % 10) ; et tu récupèreras la valeur exactement comme elle était, sous forme de string.
    Si c'est pour faire des calculs dessus, tu pourras récupérer une valeur un poil approximée avec double v = valeur / 10.;.

    Pour la classe, une clase qui traite une trame me semble inutile. En effet, il n'y a pas vraiment de dépendance entre les différentes parties de la classe : il n'y a même aucune donnée membre si l'on suit ce que tu nous as dit.

    Dès lors, pour la réutilisabilité, il est bien plus efficace de faire quelque chose comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    namespace trame {
      float DecapsuleDirectionVent(String DirectionBrute);
      // Autres fonctions utiles
    }
    Avec une fonction qui les combine toutes, avec par exemple comme prototype TrameDecomposee Unserialize(Trame const & trame) ; où TrameDecomposee est une structure contenant toutes les données utiles de la trame.

    Point intéressant : mettre le plus de fonctions possible en fonctions libres et nom en OO renforce le principe de l'OO qui en est la base : l'encapsulation.
    Contre-intuitif, mais vrai !

  12. #12
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Mini-Tyson Voir le message
    ah ok merci je ne savais pas !


    En faites je récupères une trame, je la traite pour ne prendre que la partie qui m'intéresse puis je décapsule (donc la fonction posté) pour récupérer la valeur qui m'intéresse et l'attribuer à une variable de ma classe pour pouvoir la partager et ainsi afficher ma valeur sur une IHM sous forme décimale ou traiter par un composant (genre boussole) ! Donc une précision absolue n'est pas vraiment nécessaire ni obligatoire !
    Ce genre de mesure se représente mieux en virgule fixe (donc par exemple avec un entier en multipliant la valeur par 10). Le capteur t'insère déjà une incertitude sur la mesure, ce n'est pas nécessaire d'en rajouter une liée à la représentation.

    Citation Envoyé par Mini-Tyson Voir le message
    Sinon je ne comprends pas pourquoi vous voulez sortir la fonction de la classe, je suis un peu perdu sur ce point ! Je trouve mon programme plus simple avec une classe unique qui se charge de traiter l'ensemble de la trame ainsi que la décapsulation.
    Ce n'est pas que je veuille sortir la fonction de la classe. Mais quand je vois une fonction dans une classe qui n'utilise aucune fonction membre, je soupçonne tout de suite un problème de design de la classe. D'où ma remarque

  13. #13
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    52
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 52
    Points : 29
    Points
    29
    Par défaut
    Pour la précision il s'agit de degrès, température, vitesse, ... donc ça ne se joue pas à 1 près c'est pour cela que j'indique que la précision n'est pas obligatoire !

    J'ai plusieurs fonctions qui traitent les trames car j'en ai de différents modèles (vitesse, température, degrès, ...)

    Je pense je vais fournir ma classe entière pour mettre les choses au clair car j'ai l'impression de m'embrouiller tout seul en vous expliquant

Discussions similaires

  1. Pb de formatage de champs de type float
    Par FrankyNormand dans le forum XMLRAD
    Réponses: 9
    Dernier message: 05/05/2005, 12h37
  2. [IB701] problème de float ??
    Par BoeufBrocoli dans le forum InterBase
    Réponses: 5
    Dernier message: 15/09/2003, 14h15
  3. problème de float sur SQL server 2000.
    Par fidji dans le forum MS SQL Server
    Réponses: 9
    Dernier message: 24/07/2003, 14h15
  4. [7RC3] Formatage de champs float
    Par Sylvain Leray dans le forum XMLRAD
    Réponses: 2
    Dernier message: 19/05/2003, 09h38
  5. probleme d'insertion d'un Float
    Par neness dans le forum Débuter
    Réponses: 3
    Dernier message: 07/01/2003, 12h32

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