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
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 + ib où a 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 ℝ[X] des polynômes
En mathématiques, un polynôme de la variable X peut s'écrire sous la forme :
P(X) = a0 + a1X + ... + an-1Xn-1 + anXn
Où 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 ℝ[X].
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 ℝ[X].
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 ℝ[X].
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 ℝ[X] 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 ℝ[X] qui vérifient des propriétés analogues à celles de ces opérations sur les entiers relatifs.
Par conséquent l'ensemble ℝ[X] 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 :
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 :
Code Python : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 :
Code Python : | Sélectionner tout |
1 2 | 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 :
Code Python : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 :
Code Python : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 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 (ℂ, ℝ[X], 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 :
Code Python : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | ... # 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 :
Code Python : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 :
Code Python : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 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 :
Code Python : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | ... # 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 :
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 :
Code Python : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | class Polynome: def __init__(self, liste_coefs=[0]): # 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 :
Code Python : | Sélectionner tout |
1 2 | 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 :
Code Python : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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[i] = self.coefs[i] + other.coefs[i] # 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 :
Code Python : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 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 ℝ[X] 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 ℝ[X] print(str(p) + " ∈ " + anneau(p)) |
Le code affiche :
1 + 2⋅X + X^2 ∈ ℝ[X]
1 + X ∈ ℝ[X]
(1 + 2⋅X + X^2) + (1 + X) = 2 + 3⋅X + X^2
2 + 3⋅X + X^2 ∈ ℝ[X]
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 :
Code Python : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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=[0]*(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[i1]*other.coefs[i2] # 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 :
Code Python : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 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 ℝ[X] 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 ℝ[X] print(str(p) + " ∈ " + anneau(p)) |
Le code affiche :
1 + X ∈ ℝ[X]
1 + 2⋅X ∈ ℝ[X]
(1 + X)(1 + 2⋅X) = 1 + 3⋅X + 2⋅X^2
1 + 3⋅X + 2⋅X^2 ∈ ℝ[X]
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 :
Code Python : | Sélectionner tout |
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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 | 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=[0]): # 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 dabord si le degré du polynôme est nul if (len(self.coefs)-1==0): return str(self.coefs[0]) else: # sinon if self.coefs[0]!=0: s=str(self.coefs[0]) + " + " for i in range(1, len(self.coefs)): # parcours des indices des coefficients du polynôme : [a1, a2, ..., an] if self.coefs[i]!=0: # si le coefficient de degré i n'est pas nul if self.coefs[i]!=1: # si le coefficient de degré i est différent de 1 s+="{}⋅X^{} + ".format(self.coefs[i],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[i] = self.coefs[i] + other.coefs[i] # 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=[0]*(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[i1]*other.coefs[i2] # 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([1]) 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[0] # 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 "ℝ[X]" # 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 ℝ[X] 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 ℝ[X] 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 ℝ[X] 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 ℝ[X] 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...C3%A9matiques)
https://fr.wikipedia.org/wiki/Loi_de...sition_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/referen...-numeric-types