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

Calcul scientifique Python Discussion :

Condition multiple pour classification de triangle (hyper simple mais je ne comprends pas mon erreur) [Python 3.X]


Sujet :

Calcul scientifique Python

  1. #1
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Février 2021
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2021
    Messages : 4
    Points : 3
    Points
    3
    Par défaut Condition multiple pour classification de triangle (hyper simple mais je ne comprends pas mon erreur)
    Bonjour,

    Je débute en python et mon problème risque de vous sembler trivial.

    Je suits un tutoriel trouvé sur codingame qui demande d'écrire un programme permettant d'identifier la nature d'un triangle à partir des longueurs de ses cotés.
    Voilà ce que j'ai pondu:

    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
     
    from math import *
     
    def ma_fonction(a,b,c):
     
        if a==b==c:
            return "EQUILATERAL"
        elif a==b or a==c or b==c:
            if a/b==((1+5**0.5)/2) or a/c==((1+5**0.5)/2) or b/c ==(1+5**0.5)/2 :
                return "TRIANGLE D'OR"
            elif a**2-b**2-c**2==0 or b**2-a**2-c**2==0 or c**2-a**2-b**2==0:
                return "RECTANGLE ISOCELE"
            else:
                return "ISOCELE"
        elif a**2-b**2-c**2==0 or b**2-a**2-c**2==0 or c**2-a**2-b**2==0:
            return "RECTANGLE"
        else:
            return "QUELCONQUE"
    le problème c'est que quand je tape ma_fonction(1,1,2**0.5) au lieu d'avoir "RECTANGLE ISOCELE" j'ai "ISOCELE".
    Je ne comprends pas pourquoi ma sous-condition est ignorée. Est-ce une histoire d'arrondi?

    Je vous remercie si vous pouvez m'aider. Je m'arrache les cheveux.

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut,

    Citation Envoyé par MissIsmyl Voir le message
    Est-ce une histoire d'arrondi?
    La mise au point fait partie de l'apprentissage et c'est bien de se poser des questions sur ce qu'il se passe... et un "print" des valeurs évaluées dans les conditions vous donnerait la réponse.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Février 2021
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2021
    Messages : 4
    Points : 3
    Points
    3
    Par défaut
    Ravie de cette réponse rapide!

    Je pensais que je m'étais trompé dans mon imbrication de condition.

    C'est assez fastidieux de rajouter round() à chaque terme mais ça fonctionne!

    Mon cuir chevelu et moi-même vous remercions !

  4. #4
    Membre émérite

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Points : 2 328
    Points
    2 328
    Par défaut
    En fait techniquement on ne rajoute pas round à chaque terme.
    La bonne manière de faire c'est au lieu d'écrire a==b, on test abs(a-b)<epsilon, où epsilon est qqch de petits se rapprochants de votre précision machine. On prend typiquement 1e-15.

  5. #5
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Février 2021
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2021
    Messages : 4
    Points : 3
    Points
    3
    Par défaut
    Merci de cette précision

    Voilà mon code final qui semble fonctionner sans soucis

    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
    from math import *
     
    def natureTriangle(a,b,c):
        eps= 1*exp(-15)
        if a<b+c and b<a+c and c<b+a:
            if abs(a-b)<eps and abs(b-c)<eps:
                return "EQUILATERAL"
            elif abs(a-b)<eps or abs(a-c)<eps or abs(b-c)<eps:
                if abs(a/b-((1+5**0.5)/2))<eps or abs(a/c-((1+5**0.5)/2))<eps or abs(b/c -((1+5**0.5)/2))<eps :
                    return "TRIANGLE D'OR"
                elif abs(a**2-b**2-c**2)<eps or abs(b**2-a**2-c**2)<eps or abs(c**2-a**2-b**2)<eps :
                    return "RECTANGLE ISOCELE"
                else:
                    return "ISOCELE"
            elif abs(a**2-b**2-c**2)<eps or abs(b**2-a**2-c**2)<eps or abs(c**2-a**2-b**2)<eps:
                return "RECTANGLE"
            else:
                return "QUELCONQUE"
        else:
            return("Ces longueurs ne permettent pas de former un triangle.")
     
    natureTriangle(1,1,2**0.5)

  6. #6
    Membre émérite

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Points : 2 328
    Points
    2 328
    Par défaut
    Deux remarques, pour une meilleure lisibilité de ton code :
    1) Tu peux écrire directement eps=1e-15 texto dans ton code. Qui d'ailleurs au passage n'est pas du tout la même chose que 1*exp(-15) ! 1e-15, c'est la notation scientifique, et ca vaut 1x10^(-15). Et les machines ayant souvent une précision au 16ieme chiffre, et bien on tolere que juste sur ce dernier chiffre, on puisse avoir une différence (et donc que les 15 premiers chiffres après la virgule soit pareil). Par contre exp(-15), je ne sais pas combien ca fait, ni vraiment à quoi ca pourrait correspondre...
    2) Tu peux faire une fonction, du style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def isequal(a,b, eps=1e-15):
         return abs(a-b)<eps
    comme ca dans les conditions, en faisant appel à cette fonction, on visualisera mieux ce que tu testes exactement. Car quand tu écris par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    abs(a**2-b**2-c**2)<eps
    , ca peux très bien correspondre à a²=b²+c², mais aussi à a²-b²=c². Bon c'est strictement pareil mathématiquement parlant, mais l'un à certainement un sens plus immédiat et explicite que l'autre.
    3) On ne fait pas import *, ce n'est pas bien (si de savoir pourquoi t'intéresse tu trouveras plein de ressources la dessus sur la toile).
    On fait import math, puis ensuite au lieu d'écrire abs, on écrit math.abs. Et si vraiment on veut pas écrire math.abs mais vraiment toujours abs parce que c'est plus concis, alors on fait l'import comme ca : from math import abs.

  7. #7
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Février 2021
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2021
    Messages : 4
    Points : 3
    Points
    3
    Par défaut
    Merci de toutes ces précisions

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut,

    Citation Envoyé par MissIsmyl Voir le message
    C'est assez fastidieux de rajouter round() à chaque terme mais ça fonctionne!
    2/3 choses.
    Vous testez explicitement tous les cas i.e.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        if a<b+c and b<a+c and c<b+a:
            if abs(a-b)<eps and abs(b-c)<eps:
                return "EQUILATERAL"
            elif abs(a-b)<eps or abs(a-c)<eps or abs(b-c)<eps:
                if abs(a/b-((1+5**0.5)/2))<eps or abs(a/c-((1+5**0.5)/2))<eps or abs(b/c -((1+5**0.5)/2))<eps :
                    return "TRIANGLE D'OR"
                    ....
    mais les "return" cassent la séquence.
    Autant écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        if a<b+c and b<a+c and c<b+a:
            if abs(a-b)<eps and abs(b-c)<eps:
                return "EQUILATERAL"
            if abs(a-b)<eps or abs(a-c)<eps or abs(b-c)<eps:
                if abs(a/b-((1+5**0.5)/2))<eps or abs(a/c-((1+5**0.5)/2))<eps or abs(b/c -((1+5**0.5)/2))<eps :
                    return "TRIANGLE D'OR"
                    ....
    ce qui supprime pas mal de elif/else...

    En forçant a, b, c à vérifier la condition a <= b <= c, votre code serait simplifié:
    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
    PHI = (1 + pow(5, 0.5)) / 2
     
    def ma_fonction2(a,b,c):
        assert a <= b <= c
        if a == c:
            r =  "EQUILATERAL"
        elif a == b or b==c:
            if b == c and isclose(b/a, PHI):
                r = "TRIANGLE D'OR"
            elif a == b and isclose(a**2+b**2, c**2):
                r = "RECTANGLE ISOCELE"
            else:
                r = "ISOCELE"
        elif isclose(a**2+b**2, c**2):
            r =  "RECTANGLE"
        else:
            r =  "QUELCONQUE"
        return r
    Et si je force la sortie avec des return au milieu, j'écrirai:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    def ma_fonction3(a,b,c):
        assert a <= b <= c
        if a == c:
            return "EQUILATERAL"
        if a == b or b==c:
            if b == c and isclose(b/a, PHI):
                return "TRIANGLE D'OR"
            if a == b and isclose(a**2+b**2, c**2):
                return "RECTANGLE ISOCELE"
            return "ISOCELE"
        if isclose(a**2+b**2, c**2):
            return  "RECTANGLE"
        return "QUELCONQUE"
    Juste pour vous montrer que la "logique" n'est pas la même.

    note: isclose est une fonction du module math.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Conditions multiples pour "copier" avec checkbox
    Par BenoitB31 dans le forum VBA Word
    Réponses: 2
    Dernier message: 13/04/2020, 13h14
  2. [XL-2013] Conditions multiples pour dégriser un bouton
    Par thetotof91 dans le forum Macros et VBA Excel
    Réponses: 11
    Dernier message: 12/02/2019, 21h21
  3. conditions multiples pour envoi de mail automatique
    Par molio dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 04/11/2015, 16h42
  4. [XL-MAC 2011] Conditions multiples pour QCM
    Par zouzau dans le forum Excel
    Réponses: 2
    Dernier message: 28/10/2012, 13h51
  5. [AC-2007] Requête d'apparence hyper simple mais sans solution
    Par elsergio dans le forum Requêtes et SQL.
    Réponses: 19
    Dernier message: 28/05/2011, 11h29

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