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

 C++ Discussion :

Classes: Point2D et Triangle


Sujet :

C++

  1. #1
    Membre confirmé

    Profil pro
    Étudiant
    Inscrit en
    Mars 2013
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2013
    Messages : 118
    Par défaut Classes: Point2D et Triangle
    Bonjour,

    J'ai crée une classe Point2D que voici :

    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
    19
    20
    #ifndef _POINT_H_
    #define _POINT_H_
     
    class Point2D {
        private :
        float x; // abscisse
        float y; // ordonnee
     
        public :
        Point2D();
        Point2D(float, float);
        void afficherPoint();
        float distance(Point2D);
        float getX();
        float getY();
        void setX(float);
        void setY(float);
    };
     
    #endif
    Ainsi qu'une classe Triangle :

    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
    19
    20
    #ifndef _TRIANGLE_H_
    #define _TRIANGLE_H_
     
    #include "Point2D.h"
     
    class Triangle {
        private :
        Point2D A;
        Point2D B;
        Point2D C;
     
        public :
        Triangle(Point2D, Point2D, Point2D);
        bool isocele();
        bool equilateral();
        bool rectangle();
        float perimetre();
    };
     
    #endif
    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    #include "Triangle.h"
     
    Triangle::Triangle(Point2D A, Point2D B, Point2D C):A(A),B(B),C(C) {}
     
    bool Triangle::isocele() {
        if ((A.distance(B) == B.distance(C)) ||
            (A.distance(B) == A.distance(C)) ||
            (A.distance(C) == B.distance(C))) {
                return true;
            }
        else return false;
    }
     
    bool Triangle::equilateral() {
        if ((A.distance(B) == B.distance(C)) && (A.distance(B) == A.distance(C))) {
                return true;
            }
        else return false;
    }
     
    // NE FONCTIONNE PAS
    bool Triangle::rectangle() {
        if (A.distance(B)*A.distance(B) == A.distance(C)*A.distance(C) + B.distance(C)*B.distance(C)) {
            return true;
        }
        else if (A.distance(C)*A.distance(C) == A.distance(B)*A.distance(B) + B.distance(C)*B.distance(C)) {
            return true;
        }
        else if (B.distance(C)*B.distance(C) == A.distance(C)*A.distance(C) + A.distance(B)*A.distance(B)) {
            return true;
        }
        else return false;
    }
     
    float Triangle::perimetre() {
        float resultat = 0;
        resultat += A.distance(C) + A.distance(B) + B.distance(C);
        return resultat;
    }
    Problème, ma méthode rectangle() semble ne pas fonctionner (ce qui n'est pas le cas des autres)
    En effet, quand je teste ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
       Point2D A(2,3);
        Point2D B(1,-1);
        Point2D C(6,2);
        Triangle T(A,B,C);
        cout << T.rectangle() << endl;
    Il m'affiche 0 alors que pourtant le triangle est rectangle...
    Je n'arrive pas a voir d’où vient le problème, pouvez vous m'aider ?

    Merci d'avance.

  2. #2
    Membre émérite

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Billets dans le blog
    1
    Par défaut
    Bonjour, les float n'apporte pas une précision infinie, il faudrait peut-être incorporer une marge pour comparer tes floats entre eux.

    #edit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
       Point2D A(2.0,3.0);
       Point2D B(1.0,-1.0);
       Point2D C(6.0,2.0);
       Triangle T(A,B,C);
       cout << T.rectangle() << endl;

  3. #3
    Membre confirmé

    Profil pro
    Étudiant
    Inscrit en
    Mars 2013
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2013
    Messages : 118
    Par défaut
    Bonjour PilloBuenaGente,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Point2D A(2.0,3.0);
    Point2D B(1.0,-1.0);
    Point2D C(6.0,2.0);
    Triangle T(A,B,C);
    cout << T.rectangle() << endl;
    J'ai pensé a faire ça oui.
    Malheureusement, la fonction renvoie toujours false.

  4. #4
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Ce que dit PilloBuenaGente : tu ne peux pas tester deux nombres flottants directement avec == car il faudrait être sur que la "précision" (tous les chiffres significatifs plus exactement) entre ces deux flottants sont identiques.
    PilloBuenaGente te suggère de comparer tes flottants à epsilon près. Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (std::abs(a - b) <= 0.000001) // On considère que 1 et 1.000001 sont identiques
    Pour vérifier la valeur des flottants, je te conseille de les afficher dans la fonction rectangle pour débugger.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    std::cout.precision(std::numeric_limits<float>::digits10+1); // Permet d'afficher un flottant avec toute sa précision
    std::cout << un_float;
    Sinon, j'aimerais attirer ton attention sur ta classe Point2D et plus précisément sur l'utilité des getteurs et des setteurs. Quelle(s) vérification(s) fais-tu dans les setteurs ?
    L'opérateur d'affectation = (et le constructeur par copie) sont générés par défaut ici; on a donc le droit d'écrire Point2D p(1, 2); p = Point2D(-1, -2); et cela va modifier notre point sans passer dans le setteur (selon comment tu as écrit ton constructeur).
    Bref, je pense que les getteurs et les setteurs ne sont pas justifiés et que x et y devraient être des membres publics.

  5. #5
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Salut,

    Avant toute chose, je voudrais attirer ton attention sur ta définition de la classe Point...

    Soit tu considère que c'est une classe qui a sémantique de valeur et que, si tu modifies une des valeurs qui permet de situer ton point, tu obtiens un autre point, soit tu te dis que ce n'est finalement "qu'un ensemble de données qui vont bien ensemble".

    Dans le premier cas, les mutateurs (setX et setY) sont totalement inutiles, dans le deuxième cas, c'est carrément le fait de placer x et y en accessibilité privée qui ne sert strictement à rien: faire de l'encapsulation pour le plaisir en laissant de toutes façons l'utilisateur n'en faire qu'à sa tête (comprends : pouvoir modifier l'ensemble des membres sans même s'inquiéter de la manière dont il le fait) n'a strictement aucun intérêt.

    Si je parle des deux possibilités (bien que j'aie ma préférence personnelle ), c'est simplement parce que c'est un débat qui est loin d'être terminé, et que chacun "verra midi à sa porte"

    Ceci étant dit, il faut savoir que ni le type float, ni le type double ni même le type long double (s'il est disponible) ne présentent une précision infinie.

    La raison principale est la manière dont ces valeurs sont représentées au niveau du processeur (qui, rappelons le, travaille en binaire), avec un certains nombre de bits représentant la mantisse et un certain nombre de bits représentant l'exposant.

    Mais, tout comme 1/3 ne représente pas une valeur finie en décimal (est-ce 0.3, 0.3333 ou même 0.3333333333333333333333333333 Et si on rajoutais encore une dizaine de 3 ), certaines valeurs décimales ne sont, tout simplement, pas représentables de manière finie en binaire, pour des raisons exactement similaires à celles qui font que certaines valeurs ne sont purement et simplement pas représentables de manière finie en décimale

    Une même cause ayant un même effet, tu comprendras qu'il faille décider de quand une valeur est "suffisamment proche" de l'autre pour qu'elle soit considérée comme égale (est-ce que 0.3332 est suffiamment proche de 1/3 pour être considérée comme égale, ou faut-il attendre d'avoir 0.333333333333333333333332 ).

    Cette différence "tolérable" s'appelle généralement l'epsilon.

    Chaque fois que tu veux comparer des float, des double ou même des long double (si disponibles), il faut t'assurer que la différence entre les deux est plus petite ou égale à cet epsilon (que le signe soit positif ou négatif ne change rien ).

    Le moyen le plus sur, pour un epsilon donné, tu aurais donc v1 == v2 si v1-v2 <= epsilon ou si v2- v1 < epsilon.

    C++ est vraiment généreux sur ce coup là, car il te donne une classe (numeric_limits), disponible dans l'espace de noms par simple inclusion du fichier d'en-tête <limits> qui permet d'avoir "la plus petite valeur pour laquelle x-epsilon = x = x-epsilon" pour les différents types de réels.

    elle s'utilise sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #include <limits>
    std::numeric_limits<float>::epsilon()
    Maintenant que je t'ai donné toutes les informations utiles et nécessaires, tu devrais pouvoir t'en sortir, mais n'hésites pas à revenir en cas de problème
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Membre confirmé

    Profil pro
    Étudiant
    Inscrit en
    Mars 2013
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2013
    Messages : 118
    Par défaut
    Je me demande pourquoi j'ai attendu si longtemps avant de m'inscrire sur ce forum...
    Merci à vous 3 d'avoir pris le temps de me répondre

    J'ai compris le principe, j'ai donc modifier ma fonction rectangle().

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    bool Triangle::rectangle() {
        if (abs((A.distance(B)*A.distance(B)) - (A.distance(C)*A.distance(C) + B.distance(C)*B.distance(C))) <= 0.00001) {
            return true;
        }
        else if (abs((A.distance(C)*A.distance(C)) - (B.distance(C)*B.distance(C) + A.distance(B)*A.distance(B))) <= 0.00001) {
            return true;
        }
        else if (abs((B.distance(C)*B.distance(C)) - (A.distance(B)*A.distance(B) + A.distance(B)*A.distance(B))) <= 0.00001) {
            return true;
        }
        else return false;
    }
    Ceci fonctionne.

    Mais j'ai fait l'observation suivante: 0.000001 < Epsilon < 0.00001 (car avec Epsilon <= 0.000001 ma fonction ne fonctionne plus)
    Pourtant, numeric_limits<float>::epsilon() = 0.000000119209 (soit 1.19209 * 10^-7), ce qui est largement inférieur a 0.000001 : comment ça se fait ?

    Du coup ceci rend logiquement ma fonction fausse :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        if (abs((A.distance(B)*A.distance(B)) - (A.distance(C)*A.distance(C) + B.distance(C)*B.distance(C))) <= numeric_limits<float>::epsilon()) {
            return true;
        }
    Sinon j'étais persuadé qu'il était interdit de mettre des attributs en accès privée d’où mes getteurs/setteurs.

  7. #7
    Membre émérite

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Billets dans le blog
    1
    Par défaut
    Soit tu considère que c'est une classe qui a sémantique de valeur et que, si tu modifies une des valeurs qui permet de situer ton point, tu obtiens un autre point, soit tu te dis que ce n'est finalement "qu'un ensemble de données qui vont bien ensemble".
    Je crois voir le parti pris !

    Sinon j'étais persuadé qu'il était interdit de mettre des attributs en accès privée d’où mes getteurs/setteurs.
    Si ta classe a des Getter et Setter c'est peut être alors une structure, ou bien le principe de valeur n'est pas tenu. Ils en parlent longuement dans le lien de koala01

    (Je ne connaissait pas monsieur epsilon ! Il est indispensable à connaitre dès lors qu'on ce confronte aux flottants ?!?)

    Mais j'ai fait l'observation suivante: 0.000001 < Epsilon < 0.00001 (car avec Epsilon <= 0.000001 ma fonction ne fonctionne plus)
    Pourtant, numeric_limits<float>::epsilon() = 0.000000119209 (soit 1.19209 * 10^-7), ce qui est largement inférieur a 0.000001 : comment ça se fait ?
    Comme dit koala01
    C++ est vraiment généreux sur ce coup là, car il te donne une classe (numeric_limits), disponible dans l'espace de noms par simple inclusion du fichier d'en-tête <limits> qui permet d'avoir "la plus petite valeur pour laquelle x-epsilon = x = x-epsilon" pour les différents types de réels.
    Epsilon est apparemment la valeur numérique la plus petite pour tel type de variable flottante. Ça permet de vérifier car cette valeur peut dépendre du processeur et type d'os.

    Avec ce que t'a dit Ehonn, ça devrait le faire

  8. #8
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    le epsilon n'est pas plutot définit comme le plus grand nombre tel que 1.0-epsilon == 1.0 et 1.0+epsilon == 1.0 ?

  9. #9
    Membre émérite

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Billets dans le blog
    1
    Par défaut
    le epsilon n'est pas plutot définit comme le plus grand nombre tel que 1.0-epsilon == 1.0 et 1.0+epsilon == 1.0 ?
    Je cherchait à le nommer différemment pour le visualiser..

    Pour un float = 0.1, dont sa valeur suivante est 0.101 et sa valeur inférieur 0.099,
    C'est un float dont l'epsilon est 0.001 ?, sinon il faut imaginer l'epsilon à 0.0009999999... ?

    Ou sa seule définition serait : "1.0-epsilon == 1.0 et 1.0+epsilon == 1.0" ?

  10. #10
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    la nuance est dans "le plus grand nombre transparent vis à vis de 1" (c'est à dire 0x00000000f)

Discussions similaires

  1. class upload triangle noir pour conversion jpg
    Par kate59 dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 29/10/2010, 21h19
  2. Classe pour la création d'un graphe xy
    Par Bob dans le forum MFC
    Réponses: 24
    Dernier message: 03/12/2009, 17h20
  3. Triangle Mesh Class ?
    Par tyke91 dans le forum ODE
    Réponses: 1
    Dernier message: 06/11/2008, 17h46
  4. Définir une Classe triangle
    Par Pingouin22 dans le forum C++
    Réponses: 13
    Dernier message: 16/10/2007, 10h07
  5. Réponses: 31
    Dernier message: 30/03/2006, 16h57

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