TP : classes

Objectifs et prérequis

Prérequis : cours sur la POO , exercices sur la POO

À l’issue de ce TP, vous saurez :

  • définir une classe avec un constructeur, des attributs et des méthodes ;
  • écrire des méthodes qui renvoient un booléen ou une nouvelle instance ;
  • vérifier les préconditions d’une méthode par des assertions ;
  • manipuler des objets mathématiques (intervalles, fractions) à travers le paradigme objet.

Partie 1 - Intervalles

Le but de cette partie est de construire la classe Intervalle, représentant des intervalles de nombres réels. La classe possède deux attributs borne_inf et borne_sup qui représentent respectivement la borne inférieure et la borne supérieure de l’intervalle. Ces deux bornes seront toujours considérées comme incluses.

Si borne_sup < borne_inf, l’intervalle est considéré comme vide.

  1. Programmer le constructeur de la classe. Il aura deux paramètres a et b correspondant respectivement à borne_inf et borne_sup.

    Indice

    Le constructeur range a dans self.borne_inf et b dans self.borne_sup.

  2. Écrire une méthode est_vide qui renvoie True si l’intervalle est vide, False sinon.

    Indice

    L’intervalle est vide lorsque self.borne_sup < self.borne_inf : renvoyer directement le résultat de cette comparaison, qui vaut True ou False.

  3. Écrire une méthode affichage qui renvoie une représentation de l’intervalle sous forme de chaîne de caractères : "[borne_inf; borne_sup]". Si l’intervalle est vide, l’affichage sera : "[ ]".

    Indice

    Traiter d’abord le cas vide en appelant self.est_vide(). Sinon, construire la chaîne avec une f-string à partir des deux bornes.

  4. Écrire une méthode longueur qui renvoie l’amplitude de l’intervalle. Si l’intervalle est vide, la méthode renvoie None.

    Indice

    L’amplitude est la différence entre la borne supérieure et la borne inférieure. Si self.est_vide() est vrai, renvoyer None.

  5. Écrire une méthode contient de paramètre x qui renvoie True si le réel x appartient à l’intervalle, False sinon.

    Indice

    x appartient à l’intervalle lorsque self.borne_inf <= x <= self.borne_sup.

  6. Écrire une méthode equivaut, de paramètre une (autre) instance de la classe Intervalle, qui renvoie True s’ils sont égaux, False sinon. Tous les intervalles vides sont considérés comme égaux.

    Indice

    Le paramètre est un autre objet Intervalle, appelé par exemple autre : ses bornes s’écrivent autre.borne_inf et autre.borne_sup. Si les deux intervalles sont vides, ils sont égaux ; sinon, comparer les bornes deux à deux.

    Code à copier puis compléter
        def equivaut(self, autre):
            if self.est_vide() and autre.est_vide():
                return ...
            return ... and ...
    
  7. Écrire une méthode inclus, de paramètre une instance de Intervalle, qui renvoie True si l’intervalle est inclus dans l’autre, False sinon.

    Indice

    Un intervalle vide est inclus dans tout intervalle. Sinon, l’intervalle est inclus dans autre lorsque ses deux bornes sont comprises entre celles de autre : autre.borne_inf <= self.borne_inf et self.borne_sup <= autre.borne_sup.

  8. Bonus 1. Écrire une méthode union, de paramètre une instance de la classe Intervalle, qui renvoie une instance de la classe Intervalle dont les bornes correspondent au plus petit intervalle contenant la réunion des deux intervalles.

    Indice

    Si l’un des intervalles est vide, la réunion est simplement l’autre. Sinon, le plus petit intervalle qui contient les deux va de la plus petite des bornes inférieures à la plus grande des bornes supérieures : min et max les donnent. Renvoyer un nouvel objet Intervalle(..., ...).

  9. Bonus 2. Écrire une méthode intersection, de paramètre une instance de la classe Intervalle, qui renvoie une instance de la classe Intervalle dont les bornes correspondent à l’intersection entre les deux intervalles.

    Indice

    L’intersection va de la plus grande des bornes inférieures à la plus petite des bornes supérieures. Si elle est vide, l’objet construit le sera aussi, puisque sa borne supérieure sera plus petite que sa borne inférieure.

Correction publiée après la séance.

Partie 2 - Fractions

Le but de cette partie est de construire la classe Fraction, représentant le quotient de deux nombres relatifs. La classe possèdera deux attributs numerateur et denominateur.

  1. Programmer le constructeur de la classe. Il aura deux paramètres a et b correspondant respectivement à numerateur et denominateur. On vérifiera les préconditions par des assertions : par exemple, assert b != 0, "le dénominateur ne doit pas être nul".

    Indice

    Vérifier d’abord la précondition avec assert, puis ranger a dans self.numerateur et b dans self.denominateur.

  2. Écrire une méthode affichage qui renvoie une représentation de la fraction sous forme de chaîne de caractères :

    "numerateur/denominateur".

    Si le dénominateur vaut 1 ou −1, l’affichage ne comportera pas de "/".

    Indice

    Si le dénominateur vaut 1, renvoyer le numérateur seul ; s’il vaut -1, l’opposé du numérateur (str(...) convertit un entier en chaîne). Sinon, une f-string place les deux nombres de part et d’autre de /.

  3. Écrire une méthode simplifie qui modifie les attributs numerateur et denominateur pour que la fraction soit irréductible. Si la fraction est négative, c’est le numerateur qui est négatif. Le pgcd se calcule dans cette méthode.

    Indice

    Le pgcd de deux entiers positifs se calcule par l’algorithme d’Euclide : tant que b n’est pas nul, remplacer a, b par b, a % b ; le pgcd est alors a. Diviser ensuite le numérateur et le dénominateur par ce pgcd (division entière //) ; si le dénominateur est négatif, changer le signe des deux.

    Code à copier puis compléter
        def simplifie(self):
            a, b = abs(self.numerateur), abs(self.denominateur)
            while b != 0:
                a, b = ..., ...
            self.numerateur = self.numerateur // a
            self.denominateur = ...
            if self.denominateur < 0:
                self.numerateur = ...
                self.denominateur = ...
    
  4. Écrire une méthode egal de paramètre une instance de la classe Fraction, qui renvoie True si les deux fractions sont égales, False sinon.

    Indice

    Deux fractions a/b et c/d sont égales lorsque a × d = b × c (produit en croix) : pas besoin de les simplifier.

  5. Écrire une méthode produit de paramètre une instance de la classe Fraction, qui renvoie une instance de la classe Fraction correspondant au produit des deux fractions. La nouvelle instance sera irréductible.

    Indice

    Le produit de a/b par c/d vaut (a × c)/(b × d) : construire la nouvelle Fraction, appeler sa méthode simplifie(), puis la renvoyer.

  6. Écrire une méthode quotient, de paramètre une instance de la classe Fraction, qui renvoie une instance de la classe Fraction correspondant au quotient des deux fractions. La nouvelle instance sera irréductible.

    Indice

    Diviser par c/d revient à multiplier par d/c, à condition que c ne soit pas nul.

  7. Écrire une méthode somme de paramètre une instance de la classe Fraction, qui renvoie une instance de la classe Fraction correspondant à la somme des deux fractions. La nouvelle instance sera irréductible.

    Indice

    a/b + c/d = (a × d + b × c)/(b × d) ; simplifier ensuite la nouvelle fraction.

Correction publiée après la séance.