IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Calcul formel en Python : étendre les opérations sur les nombres entiers à d'autres objets mathématiques,
Un billet blog de Denis Hulo

Le , par User

0PARTAGES

I. Introduction

On souhaite étendre les opérations d'addition et de multiplication effectuées sur les nombres entiers à d'autres objets mathématiques représentant les éléments d'un anneau.

D'après Wikipedia, en algèbre, un anneau est un ensemble muni de deux lois de composition interne appelées addition et multiplication, qui vérifient des propriétés analogues à celles de ces opérations sur les entiers relatifs.

Une loi de composition interne est une application qui, à deux éléments d'un ensemble E, associe un élément de E, comme la multiplication ou l'addition dans l'ensemble des naturels.

On va d'abord montrer brièvement dans ce billet que l'ensemble des nombres complexes et celui des polynômes sont des anneaux.

Dans un second temps, on va représenter les éléments de ces ensembles à l'aide de classes en Python, puis définir les opérations d'addition et de multiplication entre ces objets mathématiques en utilisant la surcharge d'opérateur.

Enfin, on va tester le code Python en effectuant différentes opérations sur ces nouveaux objets un peu comme on le ferait sur des nombres entiers.



II. Exemples d'anneaux

De façon plus détaillée, un anneau est un ensemble E dans lequel sont données deux lois de composition interne, notées + et ×, vérifiant les propriétés suivantes :


  • La loi + est associative : pour tous a, b, c ∈ E, a + (b + c) = (a + b) + c ;
  • La loi + est commutative : pour tous a, b ∈ E, a + b = b + a ;
  • La loi + possède un élément neutre ;
  • La loi × est associative : pour tous a, b, c ∈ E, a × (b × c) = (a × b) × c ;
  • La loi × est distributive par rapport à la loi + : pour tout a, b, c ∈ E, on a a × (b + c) = a × b + a × c et (b + c) × a = b × a + c × a ;
  • La loi × possède un élément neutre ;
  • Tout élément a appartenant à l'ensemble E possède un opposé, noté –a.

    Note : si on veut être précis, on devrait plutôt parler d'anneau unitaire.


    Nous allons donc le vérifier maintenant sur deux exemples.


    II-A. Ensemble ℂ des nombres complexes

    651319

    En mathématiques, l'ensemble des nombres complexes, noté , est créé comme extension de l'ensemble des nombres réels, contenant en particulier un nombre imaginaire noté i, tel que i2 = −1. Le carré de (−i) est aussi égal à −1 : (−i)2 = −1.

    Tout nombre complexe peut s'écrire sous la forme a + iba et b sont des nombres réels.

    II-A-1. Addition de nombres complexes

    L'addition de 2 nombres complexes z1 = a + ib et z2 = c + id écrits sous forme algébrique, est définie de la manière suivante :

    (a + ib) + (c + id) = (a+b) + i(b+d)

    Le résultat donne également un nombre complexe et cette opération est donc bien une loi de composition interne dans .

    Soient maintenant les trois nombres complexes z1, z2 et z3

    1) Associativité

    On vérifie facilement en utilisant l'égalité précédente la propriété d'associativité de l'addition de nombres complexes :

    z1 + (z2 + z3) = (z1 + z2) + z3


    2) et 3) On peut montrer également que l'addition est commutative et que le complexe nul est l'élément neutre pour l'addition dans .


    II-A-2. Multiplication de nombres complexes

    La multiplication de 2 nombres complexes z1 = a + ib et z2 = c + id, est définie par :

    (a + ib) × (c + id) = (ac - bd) + i(ad + bc)

    Le résultat de la multiplication de deux nombres complexes donne aussi un nombre complexe et cette opération est donc bien une loi de composition interne dans .


    Soient maintenant les nombres complexes z1, z2 et z3

    4) Associativité

    On vérifie facilement en utilisant l'égalité précédente la propriété d'associativité de la multiplication :

    z1 × (z2 × z3) = (z1 × z2) × z3


    5) Distributivité par rapport à l'addition

    De même, on vérifie aisément la propriété de distributivité de la multiplication par rapport à l'addition :

    z1 × (z2 + z3) = z1 × z2 + z1 × z3

    (z2 + z3) × z1 = z2 × z1 + z3 × z1


    6) et 7) On peut montrer enfin que le nombre 1 est l'élément neutre pour la multiplication dans et que tout élément de cet ensemble possède un opposé.


    En conclusion, les opérations d'addition et de multiplication sont des lois de composition interne dans l'ensemble qui vérifient des propriétés analogues à celles de ces opérations sur les entiers relatifs.

    Par conséquent l'ensemble constitue un anneau.


    II-B. Ensemble ℝ des polynômes

    651320

    En mathématiques, un polynôme de la variable X peut s'écrire sous la forme :

    P(X) = a0 + a1X + ... + an-1Xn-1 + anXn

    X est une variable appelée indéterminée (dans notre cas un réel), les constantes a0, a1, ..., an sont les coefficients réels du polynôme et n est un entier naturel.


    II-B-1. Addition de polynômes

    Soient 2 polynômes de la forme :

    P1(X) = a0 + a1X + ... + an-1Xn-1 + anXn
    P2(X) = b0 + b1X + ... + bm-1Xm-1 + bnXm


    L'addition de ces 2 polynômes P1(X) et P2(X) donne pour n=m :

    P1(X) + P2(X) = (a0 + b0) + (a1 + b1)X + ... + (an-1 + bn-1)Xn-1 + (an + bn)Xn

    Et pour n>m :

    P1(X) + P2(X) = (a0 + b0) + (a1 + b1)X + ... + (am-1 + bm-1)Xm-1 + (am + bm)Xm + ... + anXn

    On additionne donc simplement les coefficients de même degré et on obtient donc un troisième polynôme.

    Par conséquent, cette opération est bien une loi de composition interne dans .


    Soient maintenant les trois polynômes P1, P2 et P3

    1) Associativité

    On vérifie facilement en utilisant le résultat précédent la propriété d'associativité de l'addition de polynômes :

    P1 + (P2 + P3) = (P1 + P2) + P3


    2) et 3) On peut montrer également que l'addition est commutative et que le polynôme nul est l'élément neutre pour l'addition dans .


    II-B-2. Multiplication de polynômes

    Soient 2 polynômes de degré 1 :

    P1(X) = a0 + a1X
    P2(X) = b0 + b1X

    La multiplication étant distributive par rapport à l'addition, le produit de ces 2 polynômes P1(X) et P2(X) nous donne :

    P1(X) X P2(X) = (a0 + a1X)(b0 + b1X)
    P1(X) X P2(X) = a0b0 + a0b1X + a1b0X + a1b1X2

    On obtient donc à nouveau un troisième polynôme, et on peut ainsi généraliser facilement ce résultat à des polynômes de degrés quelconques.

    Par conséquent, cette opération est bien une loi de composition interne dans .


    Soient maintenant les polynômes P1, P2 et P3

    4) Associativité

    On vérifie facilement en utilisant le résultat précédent la propriété d'associativité de la multiplication :

    P1 × (P2 × P3) = (P1 × P2) × P3


    5) Distributivité par rapport à l'addition

    De même, on vérifie aisément la propriété de distributivité de la multiplication de polynômes par rapport à l'addition :

    P1 × (P2 + P3) = P1 × P2 + P1 × P3

    (P2 + P3) × P1 = P2 × P1 + P3 × P1


    6) et 7) On peut montrer enfin que le polynôme constant 1 est l'élément neutre pour la multiplication dans et que tout élément de cet ensemble possède un opposé.


    En conclusion, les opérations d'addition et de multiplication sont des lois de composition interne dans l'ensemble qui vérifient des propriétés analogues à celles de ces opérations sur les entiers relatifs.

    Par conséquent l'ensemble constitue un anneau.



    III. Implémentation en Python

    Les opérations d'addition et de multiplication sur ces objets mathématiques ont donc des propriétés communes avec celles sur les nombres entiers, toutefois elles ont aussi leurs particularités et ne sont pas définies de la même manière (on parle dans ce cas de polymorphisme).

    On va maintenant représenter les nombres complexes et les polynômes à l'aide de classes en Python, puis définir les opérations d'addition et de multiplication entre ces objets mathématiques en utilisant la surcharge d'opérateur.


    III-A. Création de la classe Complexe

    Pour définir ces nombres complexes en Python et pouvoir réaliser des opérations entre eux, il nous faut créer une classe Complexe :

    651443

    Notre classe comportera en plus une méthode particulière __init__() dont le code est exécuté quand la classe est instanciée.

    Elle va nous permettre de définir les parties réelle et imaginaire du nombre complexe au moment de créer l'objet :

    class Complexe:

    def __init__(self, part_reel=0, part_imag=0):
    # méthode constructeur de la classe

    # on définit la partie réelle du nombre complexe
    self.reel = part_reel

    # on définit la partie imaginaire du nombre complexe
    self.imag = part_imag

    def __str__(self):
    # permet d'afficher le nombre complexe sous la forme algébrique a + bi

    return "{0} + {1}i".format(self.reel, self.imag) if self.imag>=0 else "{0} - {1}i".format(self.reel, abs(self.imag))

    La méthode __str__ permet d'afficher un nombre complexe sous la forme a + bi.

    Pour tester ces méthodes, nous ajoutons simplement deux lignes au module :

    z = Complexe(1, 2) # création de l'objet Complexe : 1 + 2i
    print(z) # affiche le nombre complexe

    Le code affiche :

    1 + 2i


    III-A-1. Surcharge de l'opérateur d'addition

    Pour surcharger l'opérateur « + » et pouvoir ainsi réaliser l'addition de 2 nombres complexes, nous devons ajouter une méthode __add __ () à la classe :

    class Complexe:
    ....

    def __add__(self, other):
    # méthode permettant de redéfinir l'opérateur « + » pour 2 nombres complexes : z1 + z2 = (a + bi) + (c + di) = (a+c) + (b+d)i

    # on évalue la partie réelle du nombre complexe résultat de l'addition
    part_reel = self.reel + other.reel

    # on évalue la partie imaginaire du nombre complexe résultat de l'addition
    part_imag = self.imag + other.imag

    # renvoie le nombre complexe résultat de l'addition
    return Complexe(part_reel, part_imag)


    Cette méthode permet donc de redéfinir l'opération « + » pour les nombres complexes en utilisant l'égalité :

    (a + bi) + (c + di) = (a+c) + (b+d)i


    Pour tester l'opérateur d'addition portant sur 2 objets de la classe Complexe, nous ajoutons ces lignes de code :

    # création du 1er objet de la classe Complexe : 1 + 2i
    z1 = Complexe(1, 2)

    # création de 2e objet Complexe : 2 + 3i
    z2 = Complexe(2, 3)

    # affiche l'appartenance de z1 et z2 à l'ensemble ℂ
    print(str(z1) + " ∈ " + anneau(z1))
    print(str(z2) + " ∈ " + anneau(z2))

    print()

    # addition des 2 nombres complexes
    z = z1+z2

    # affiche le résultat de l'addition
    print("(" + str(z1) + ")" + " + " + "(" + str(z2) + ")" + " = " + str(z))
    print()

    # affiche l'appartenance de z à l'ensemble ℂ
    print(str(z) + " ∈ " + anneau(z))


    Le code affiche :

    1 + 2i ∈ ℂ
    2 + 3i ∈ ℂ

    (1 + 2i) + (2 + 3i) = 3 + 5i

    3 + 5i ∈ ℂ


    La fonction anneau(element) renvoie l'ensemble (ℂ, ℝ, etc.) auquel appartient l'élément, elle est présente dans le module donné à la fin du billet.


    On peut également vérifier la propriété d'associativité de l'addition :

    ...
    # création de 3e objet Complexe : 2 + 2i
    z3 = Complexe(2, 2)

    # affiche les nombres complexes z1, z2 et z2
    print("z1 = " + str(z1))
    print("z2 = " + str(z2))
    print("z3 = " + str(z3))

    # vérification de la propriété d'associativité de l'addition dans ℂ
    r1 = z1 + (z2 + z3)
    r2 = (z1 + z2) + z3

    print()

    if r1==r2: # si r1=r2
    print("z1 + (z2 + z3) = (z1 + z2) + z3")
    else:
    print("z1 + (z2 + z3) ≠ (z1 + z2) + z3")


    Le code affiche :

    z1 = 1 + 2i
    z2 = 2 + 3i
    z3 = 2 + 2i

    z1 + (z2 + z3) = (z1 + z2) + z3



    III-A-2. Surcharge de l'opérateur de multiplication

    Pour surcharger l'opérateur « * » et l'appliquer à 2 nombres complexes, nous devons également ajouter une méthode __mul __ () à la classe :

    class Complexe:
    ...
    def __mul__(self, other):
    # méthode permettant de redéfinir l'opérateur « * » pour 2 nombres complexes : z1 * z2 = (ac - bd) + (ad + bc)*i

    # part_reel = (ac - bd)
    part_reel = self.reel * other.reel - self.imag * other.imag

    # part_imag = (ad + bc)
    part_imag = self.reel * other.imag + self.imag * other.reel

    # renvoie le nombre complexe résultat de la multiplication
    return Complexe(part_reel, part_imag)


    Cette méthode offre donc la possibilité de redéfinir l'opération de multiplication pour 2 nombres complexes en utilisant l'égalité :

    (a + bi) x (c + di) = (ac - bd) + (ad + bc)i


    Pour tester l'opérateur de multiplication portant sur 2 objets de la classe Complexe, nous ajoutons ces lignes :

    # création du 1er objet de la classe Complexe : 1 + 2i
    z1 = Complexe(1, 2)

    # création du 2e objet de la classe Complexe : 2 + 3i
    z2 = Complexe(2, 3)

    # affiche l'appartenance de z1 et z2 à l'ensemble ℂ
    print(str(z1) + " ∈ " + anneau(z1))
    print(str(z2) + " ∈ " + anneau(z2))

    print()

    # produit des 2 nombres complexes
    z = z1*z2

    # affiche le résultat du produit
    print("(" + str(z1) + ")" + "(" + str(z2) + ")" + " = " + str(z))
    print()

    # affiche l'appartenance de z à l'ensemble ℂ
    print(str(z) + " ∈ " + anneau(z))


    Le code affiche :

    1 + 2i ∈ ℂ
    2 + 3i ∈ ℂ

    (1 + 2i)(2 + 3i) = -4 + 7i

    -4 + 7i ∈ ℂ


    On peut également vérifier la propriété d'associativité de la multiplication :

    ...
    # création de 3e objet Complexe : 2 + 2i
    z3 = Complexe(2, 2)

    # affiche les nombres complexes z1, z2 et z2
    print("z1 = " + str(z1))
    print("z2 = " + str(z2))
    print("z3 = " + str(z3))

    # vérification de la propriété d'associativité de la multiplication dans ℂ
    r1 = z1 * (z2 * z3)
    r2 = (z1 * z2) * z3

    print()

    if r1==r2: # si r1=r2
    print("z1 * (z2 * z3) = (z1 * z2) * z3")
    else:
    print("z1 * (z2 * z3) ≠ (z1 * z2) * z3")


    Le code affiche :

    z1 = 1 + 2i
    z2 = 2 + 3i
    z3 = 2 + 2i

    z1 * (z2 * z3) = (z1 * z2) * z3



    III-B. Création de la classe Polynome

    Pour définir ces polynômes en Python et pouvoir réaliser des opérations entre eux, il nous faut créer une classe Polynome :

    651444

    Sa méthode constructeur __init__() va nous permettre de définir la liste des coefficients du polynôme au moment de créer l'objet :

    class Polynome:

    def __init__(self, liste_coefs=):
    # méthode constructeur de la classe

    # on définit la liste des coefficients du polynôme [a0, a1, ..., an]
    self.coefs = liste_coefs

    # suppression si nécessaire des zéros en queue de liste de coefficients. Exemple : [2, 3, 1, 0, 0] -> [2, 3, 1]
    self.reduire()

    def __str__(self):
    ...

    La méthode __str__ permet d'afficher un polynôme sous la forme 1 + 2.x + x^2.

    Pour tester ces méthodes, nous ajoutons deux lignes au module :

    p = Polynome([1, 2, 1]) # création de l'objet Polynome : 1 + 2x + x^2
    print(p) # affiche l'expression du polynôme

    Le code affiche :

    1 + 2⋅X + X^2


    Note importante : la liste de coefficients permettant de créer l'objet Polynome contient également les coefficients nuls.

    Par exemple, le polynôme P(x) = x^2 + 2⋅X^4 sera représenté par la liste [0, 0, 1, 0, 2] .


    III-B-1. Surcharge de l'opérateur d'addition

    Pour surcharger l'opérateur « + » et pouvoir ainsi réaliser l'addition de 2 polynômes, nous devons ajouter une méthode __add __ () à la classe :

    class Polynome:
    ...
    def __add__(self, other):
    # méthode permettant de redéfinir l'opérateur « + » pour 2 polynômes : (1 + 2x + x^2) + (1 + x) = 2 + 3x + x^2

    # p1 = self, p2 = other
    if len(other.coefs) >len(self.coefs): # si degré de p2 > degré de p1
    # on copie les coefs du polynôme de degré le plus élevé et la longueur de la liste de coefs la plus petite.
    liste_coefs = other.coefs[:]; n = len(self.coefs)
    else: liste_coefs = self.coefs[:]; n = len(other.coefs) # sinon, ...

    for i in range(n): # parcours des indices de liste_coefs
    liste_coefs = self.coefs + other.coefs # addition des coefficients de degré i

    # renvoie le polynôme résultat de l'addition
    return Polynome(liste_coefs)


    Cette méthode permet donc de redéfinir l'opération « + » pour les polynômes en additionnant les coefficients de même degré.


    Pour tester l'opérateur d'addition portant sur 2 objets de la classe Polynome, nous ajoutons ces lignes de code :

    # création du 1er objet de la classe Polynome : 1 + 2x + x^2
    p1 = Polynome([1, 2, 1])

    # création du 2e objet Polynome : 1 + x
    p2 = Polynome([1, 1])

    # affiche l'appartenance de p1 et p2 à l'ensemble ℝ
    print(str(p1) + " ∈ " + anneau(p1))
    print(str(p2) + " ∈ " + anneau(p2))

    print()

    # addition des 2 polynômes
    p = p1+p2

    # affiche le résultat de l'addition
    print("(" + str(p1) + ")" + " + " + "(" + str(p2) + ")" + " = " + str(p))
    print()

    # affiche l'appartenance de p à l'ensemble ℝ
    print(str(p) + " ∈ " + anneau(p))


    Le code affiche :

    1 + 2⋅X + X^2 ∈ ℝ
    1 + X ∈ ℝ

    (1 + 2⋅X + X^2) + (1 + X) = 2 + 3⋅X + X^2

    2 + 3⋅X + X^2 ∈ ℝ



    III-B-2. Surcharge de l'opérateur de multiplication

    Pour surcharger l'opérateur « * » et l'appliquer à 2 polynômes, nous devons également ajouter une méthode __mul __ () à la classe :

    class Polynome:
    ...
    def __mul__(self, other):
    # méthode permettant de redéfinir l'opérateur « * » pour 2 polynômes : (1 + x) * (1 + 2x) = 1 + 3x + 2x^2

    # initialisation de la liste des coefficients qu'avec des zéros
    liste_coefs=*(len(self.coefs)+len(other.coefs)-1) # exemple : [0, 0, 0]
    for i1 in range(len(self.coefs)): # parcours des indices des coefs du polynôme n°1
    for i2 in range(len(other.coefs)): # parcours des indices des coefs du polynôme n°2
    # multiplication des coefficients d'indices i1 et i2
    liste_coefs[i1+i2] = liste_coefs[i1+i2] + self.coefs*other.coefs

    # création de l'objet Polynome basé sur la liste
    poly=Polynome(liste_coefs)

    return poly # renvoie le polynôme résultat de la multiplication


    Cette méthode permet donc de redéfinir l'opération de multiplication pour 2 polynômes en utilisant la propriété de distributivité de la multiplication par rapport à l'addition.


    Pour tester l'opérateur de multiplication portant sur 2 objets de la classe Polynome, nous ajoutons simplement ces lignes :

    # création du 1er objet de la classe Polynome : 1 + x
    p1 = Polynome([1, 1])

    # création du 2e objet de la classe Polynome : 1 + 2x
    p2 = Polynome([1, 2])

    # affiche l'appartenance de p1 et p2 à l'ensemble ℝ
    print(str(p1) + " ∈ " + anneau(p1))
    print(str(p2) + " ∈ " + anneau(p2))

    print()

    # produit des 2 polynômes
    p = p1*p2

    # affiche le résultat de la multiplication de p1 par p2
    print("(" + str(p1) + ")" + "(" + str(p2) + ")" + " = " + str(p))
    print()

    # affiche l'appartenance de p à l'ensemble ℝ
    print(str(p) + " ∈ " + anneau(p))


    Le code affiche :

    1 + X ∈ ℝ
    1 + 2⋅X ∈ ℝ

    (1 + X)(1 + 2⋅X) = 1 + 3⋅X + 2⋅X^2

    1 + 3⋅X + 2⋅X^2 ∈ ℝ


    On peut bien sûr imaginer d'étendre à ces objets mathématiques d'autres opérations effectuées sur les nombres entiers (soustraction, puissance, etc.).



    IV. Module complet

    On donne pour finir le code complet du module contenant les deux classes :

    class Complexe:

    def __init__(self, part_reel=0, part_imag=0):
    # méthode constructeur de la classe

    # on définit la partie réelle du nombre complexe
    self.reel = part_reel

    # on définit la partie imaginaire du nombre complexe
    self.imag = part_imag

    def __str__(self):
    # permet d'afficher le nombre complexe sous la forme algébrique a + bi

    return "{0} + {1}i".format(self.reel, self.imag) if self.imag>=0 else "{0} - {1}i".format(self.reel, abs(self.imag))

    def __add__(self, other):
    # méthode permettant de redéfinir l'opérateur « + » pour 2 nombres complexes : z1 + z2 = (a + bi) + (c + di) = (a+c) + (b+d)i

    # on évalue la partie réelle du nombre complexe résultat de l'addition
    part_reel = self.reel + other.reel

    # on évalue la partie imaginaire du nombre complexe résultat de l'addition
    part_imag = self.imag + other.imag

    # renvoie le nombre complexe résultat de l'addition
    return Complexe(part_reel, part_imag)

    def __mul__(self, other):
    # méthode permettant de redéfinir l'opérateur « * » pour 2 nombres complexes : z1 * z2 = (ac - bd) + (ad + bc)*i

    # part_reel = (ac - bd)
    part_reel = self.reel * other.reel - self.imag * other.imag

    # part_imag = (ad + bc)
    part_imag = self.reel * other.imag + self.imag * other.reel

    # renvoie le nombre complexe résultat de la multiplication
    return Complexe(part_reel, part_imag)

    def __pow__(self, n):
    # méthode permettant de redéfinir l'opérateur de puissance : self ** n

    # on initialise la variable objet z avec la valeur 1 élément neutre pour la multiplication de nombres complexes
    z = Complexe(1,0)

    # nous multiplions n fois z par self à l'aide de l'opérateur *
    for i in range(n):
    z = z*self # équivalent à : z = z.__mul__(self)

    # renvoie le nombre complexe résultat de l'opération (self ** n)
    return z

    def __eq__(self, other):
    # méthode permettant de redéfinir l'opérateur « == » pour 2 nombres complexes

    # renvoie True si les parties réelles et imaginaires des 2 nombres complexes sont égales
    return (self.reel==other.reel) and (self.imag==other.imag)


    class Polynome:

    def __init__(self, liste_coefs=):
    # méthode constructeur de la classe

    # on définit la liste des coefficients du polynôme [a0, a1, ..., an]
    self.coefs = liste_coefs

    # suppression si nécessaire des zéros en queue de liste de coefficients. Exemple : [2, 3, 1, 0, 0] -> [2, 3, 1]
    self.reduire()


    def __str__(self): # permet d'afficher le polynôme sous la forme 1 + 2x + 3x^2
    s="" # initialisation de la chaîne de caractères
    # on vérifie d’abord si le degré du polynôme est nul
    if (len(self.coefs)-1==0):
    return str(self.coefs)
    else: # sinon
    if self.coefs!=0:
    s=str(self.coefs) + " + "
    for i in range(1, len(self.coefs)): # parcours des indices des coefficients du polynôme : [a1, a2, ..., an]
    if self.coefs!=0: # si le coefficient de degré i n'est pas nul
    if self.coefs!=1: # si le coefficient de degré i est différent de 1
    s+="{}⋅X^{} + ".format(self.coefs,i)
    else: s+="X^{} + ".format(i)

    # élimination des caractères en trop
    s = s[:-3].replace("+ -", "- ").replace("X^1 ","X ").replace(" 1⋅X"," X")
    if s[-2:]=="^1": s = s[:-2]
    if s[:3]=="1⋅X": s = s[3:]

    return s # on retourne l'expression du polynôme

    def eval_degre(): # retourne le degré du polynôme
    return (len(self.coefs)-1)

    def __add__(self, other):
    # méthode permettant de redéfinir l'opérateur « + » pour 2 polynômes : (1 + 2x + x^2) + (1 + x) = 2 + 3x + x^2

    # p1 = self, p2 = other
    if len(other.coefs) >len(self.coefs): # si degré de p2 > degré de p1
    # on copie les coefs du polynôme de degré le plus élevé et la longueur de la liste de coefs la plus petite.
    liste_coefs = other.coefs[:]; n = len(self.coefs)
    else: liste_coefs = self.coefs[:]; n = len(other.coefs) # sinon, ...

    for i in range(n): # parcours des indices de liste_coefs
    liste_coefs = self.coefs + other.coefs # addition des coefficients de degré i

    # renvoie le polynôme résultat de l'addition
    return Polynome(liste_coefs)

    def reduire(self):
    # tant que le dernier élément de la liste est nul
    while self.coefs[-1] == 0 and len(self.coefs)>1:
    self.coefs.pop() # supprimer le dernier élément

    def __mul__(self, other):
    # méthode permettant de redéfinir l'opérateur « * » pour 2 polynômes : (1 + x) * (1 + 2x) = 1 + 3x + 2x^2

    # initialisation de la liste des coefficients qu'avec des zéros
    liste_coefs=*(len(self.coefs)+len(other.coefs)-1) # exemple : [0, 0, 0]
    for i1 in range(len(self.coefs)): # parcours des indices des coefs du polynôme n°1
    for i2 in range(len(other.coefs)): # parcours des indices des coefs du polynôme n°2
    # multiplication des coefficients d'indices i1 et i2
    liste_coefs[i1+i2] = liste_coefs[i1+i2] + self.coefs*other.coefs

    # création de l'objet Polynome basé sur la liste
    poly=Polynome(liste_coefs)

    return poly # renvoie le polynôme résultat de la multiplication

    def __pow__(self, n): # méthode permettant de redéfinir l'opérateur de puissance : self ** n
    # on crée l'objet poly à partir d'une liste contenant un seul élément 1, élément neutre pour la multiplication des polynômes
    poly = Polynome()

    for i in range(n): # on multiplie n fois poly par self à l'aide de l'opérateur *
    poly = poly*self # équivalent à : poly = poly.__mul__(self)

    return poly # renvoie le polynôme résultat de l'opération (self ** n)

    def __eq__(poly1, other): # méthode permettant de redéfinir l'opérateur « == » pour 2 polynômes

    return (poly1.coefs==other.coefs) # renvoie True si les 2 liste de coefficients sont égales

    def eval(self,x): # méthode permettant d'évaluer le polynôme en fonction de x
    # intialisation des variables
    valeur_polynome = self.coefs # valeur_polynome = a0
    power=1

    for coef in self.coefs[1:]: # parcours des coefficients du polynôme à partir de a1 : a1, a2, ..., an
    power = power*x # calcul de la puissance de x pour ai : power = x^i
    valeur_polynome += coef*power # valeur_polynome = valeur_polynome + ai*x^i

    return valeur_polynome # renvoie la valeur du polynôme

    def eval_horner(self,x): # méthode permettant d'évaluer le polynôme en fonction de x
    # intialisation de la variable
    valeur_polynome = self.coefs[-1] # valeur_polynome = an

    for coef in reversed(self.coefs[:-1]): # parcours des coefficients du polynôme à partir de an-1 : an-1, ..., a1, a0
    valeur_polynome = valeur_polynome*x + coef # valeur_polynome = valeur_polynome*x + ai

    return valeur_polynome # renvoie la valeur du polynôme


    def anneau(element):
    # retourne l'ensemble ou l'anneau auquel appartient l'élément passé en argument

    # si c'est un objet Complexe
    if isinstance(element, Complexe):
    return "ℂ"
    # si c'est un objet Polynome
    elif isinstance(element, Polynome):
    return "ℝ"
    # si c'est un entier
    elif isinstance(element, int):
    return "Z"
    else: # sinon
    return ""


    # addition de 2 nombres complexes

    print("I-A. Addition de 2 nombres complexes\n")

    # création du 1er objet de la classe Complexe : 1 + 2i
    z1 = Complexe(1, 2)

    # création de 2e objet Complexe : 2 + 3i
    z2 = Complexe(2, 3)

    # affiche l'appartenance de z1 et z2 à l'ensemble ℂ
    print(str(z1) + " ∈ " + anneau(z1))
    print(str(z2) + " ∈ " + anneau(z2))

    print()

    # addition des 2 nombres complexes
    z = z1+z2

    # affiche le résultat de l'addition
    print("(" + str(z1) + ")" + " + " + "(" + str(z2) + ")" + " = " + str(z))
    print()

    # affiche l'appartenance de z à l'ensemble ℂ
    print(str(z) + " ∈ " + anneau(z))

    print()

    print("Vérification de l'associativité de l'addition dans ℂ\n")

    # création de 3e objet Complexe : 2 + 2i
    z3 = Complexe(2, 2)

    # affiche les nombres complexes z1, z2 et z2
    print("z1 = " + str(z1))
    print("z2 = " + str(z2))
    print("z3 = " + str(z3))

    # vérification de la propriété d'associativité de l'addition dans ℂ
    r1 = z1 + (z2 + z3)
    r2 = (z1 + z2) + z3

    print()

    if r1==r2: # si r1=r2
    print("z1 + (z2 + z3) = (z1 + z2) + z3")
    else:
    print("z1 + (z2 + z3) ≠ (z1 + z2) + z3")

    print();print()

    # multiplication de 2 nombres complexes

    print("I-B. Multiplication de 2 nombres complexes\n")

    # création du 1er objet de la classe Complexe : 1 + 2i
    z1 = Complexe(1, 2)

    # création du 2e objet de la classe Complexe : 2 + 3i
    z2 = Complexe(2, 3)

    # affiche l'appartenance de z1 et z2 à l'ensemble ℂ
    print(str(z1) + " ∈ " + anneau(z1))
    print(str(z2) + " ∈ " + anneau(z2))

    print()

    # produit des 2 nombres complexes
    z = z1*z2

    # affiche le résultat du produit
    print("(" + str(z1) + ")" + "(" + str(z2) + ")" + " = " + str(z))
    print()

    # affiche l'appartenance de z à l'ensemble ℂ
    print(str(z) + " ∈ " + anneau(z))

    print()

    print("Vérification de l'associativité de la multiplication dans ℂ\n")

    # affiche les nombres complexes z1, z2 et z2
    print("z1 = " + str(z1))
    print("z2 = " + str(z2))
    print("z3 = " + str(z3))

    # vérification de la propriété d'associativité de la multiplication dans ℂ
    r1 = z1 * (z2 * z3)
    r2 = (z1 * z2) * z3

    print()

    if r1==r2: # si r1=r2
    print("z1 * (z2 * z3) = (z1 * z2) * z3")
    else:
    print("z1 * (z2 * z3) ≠ (z1 * z2) * z3")

    print();print()


    # addition de 2 polynômes

    print("II-A. Addition de 2 polynômes\n")

    # création du 1er objet de la classe Polynome : 1 + 2x + x^2
    p1 = Polynome([1, 2, 1])

    # création du 2e objet Polynome : 1 + x
    p2 = Polynome([1, 1])

    # affiche l'appartenance de p1 et p2 à l'ensemble ℝ
    print(str(p1) + " ∈ " + anneau(p1))
    print(str(p2) + " ∈ " + anneau(p2))

    print()

    # addition des 2 polynômes
    p = p1+p2

    # affiche le résultat de l'addition
    print("(" + str(p1) + ")" + " + " + "(" + str(p2) + ")" + " = " + str(p))
    print()

    # affiche l'appartenance de p à l'ensemble ℝ
    print(str(p) + " ∈ " + anneau(p))

    print();print()

    # multiplication de 2 polynômes

    print("II-B. Multiplication de 2 polynômes\n")

    # création du 1er objet de la classe Polynome : 1 + x
    p1 = Polynome([1, 1])

    # création du 2e objet de la classe Polynome : 1 + 2x
    p2 = Polynome([1, 2])

    # affiche l'appartenance de p1 et p2 à l'ensemble ℝ
    print(str(p1) + " ∈ " + anneau(p1))
    print(str(p2) + " ∈ " + anneau(p2))

    print()

    # produit des 2 polynômes
    p = p1*p2

    # affiche le résultat de la multiplication de p1 par p2
    print("(" + str(p1) + ")" + "(" + str(p2) + ")" + " = " + str(p))
    print()

    # affiche l'appartenance de p à l'ensemble ℝ
    print(str(p) + " ∈ " + anneau(p))



    V. Conclusion

    Comme on a pu le montrer, l'ensemble des nombres complexes et celui des polynômes constituent donc des anneaux munis de lois de composition interne, à savoir l'addition et la multiplication.

    Les éléments de ces anneaux peuvent facilement être représentés en Python afin de pouvoir ensuite réaliser des opérations entre ces objets mathématiques, un peu comme on le ferait sur des nombres entiers.

    Ces opérations peuvent bien sûr être étendues à d'autres objets mathématiques, comme par exemple les fonctions continues ou les séries formelles.


    Sources :

    https://fr.wikipedia.org/wiki/Anneau_(math%C3%A9matiques)
    https://fr.wikipedia.org/wiki/Loi_de_composition_interne
    https://fr.wikipedia.org/wiki/Nombre_complexe
    https://fr.wikipedia.org/wiki/Polyn%C3%B4me
    https://fr.wikipedia.org/wiki/Calcul_formel
    https://docs.python.org/fr/3/tutorial/classes.html
    https://docs.python.org/fr/3/reference/datamodel.html#emulating-numeric-types
  • Vous avez lu gratuitement 3 090 articles depuis plus d'un an.
    Soutenez le club developpez.com en souscrivant un abonnement pour que nous puissions continuer à vous proposer des publications.

    Une erreur dans cette actualité ? Signalez-nous-la !