Vous êtes sur la page 1sur 11

M.

Rezzouk Aide-mémoire Python

Nombres, variables, entrée/sortie


Python Explications

a = 5 a est la référence sur une boîte mémoire d’un entier, d’un flottant
a = 3.7 ou d’une chaîne de caractères etc.
a = "coucou" En entrée dans une fonction, def f(a): a représente la référence
a = 'coucou' (pointeur) donc attention aux effets de bord pour les listes, les dic-
a = '''une autre chaîne tionnaires (tous les objets mutables), pas de problème en revanche
sur plusieurs lignes''' pour les type str, int, float. (id(a) pour connaître le numéro
d’indentification de l’objet a), voir Fonctions.

a = float("353.45")
convertit la valeur en flottant, chaîne de caractères...
a = str(312)
La variable a peut changer de type (typage dynamique)
ascii = ord('a')

a, b = 12, 4.5 affectations en chaîne (tout est évalué à droite avant d’être affecté)
c = [k**2 for k in range(10) if k%5 != 0] création de liste par « compréhension »

+ - * ** % // / opérateurs classiques % = modulo, // = quotient entier (python


3), / division en flottant

a = round(1/3, 3) # approx. à 1e-3


a = abs(-3.7) fonctions sur les flottants classiques

a = 1e15 écriture scientifique 1015

a = 5-2*j
a.real
a.imag nombre complexe 5 − 2i, type complex
abs(a)

not, and, or, True (1),


False (0), ==, !=, <= ... logique

val = input("Entrer une valeur")


print("{} objets parmi {}".format(nb1, nb2)) entrée et affichage

Types courants

a, b, c, d = 123, -5.6, 'coucou', "l'appel" entier (int), flottant (float), chaînes de caractères (str) non
modifiable (immutable)

a = (23, "truc", -5)


b = [23, "truc", -5] n-uplet (tuple) non modifiable (immutable) liste (liste) mo-
dico = { "cle1": 243, "cle2": -56} difiable (mutable) dictionnaire (dict) modifiable (mutable)
ensemble = {1, 2, 3, "coucou"} ensemble (set) modifiable (mutable)

a = str(-56)
b = int("678")
L = list("coucou") conversions... L vaut [’c’, ’o’, ’u’, ’c’, ’o’, ’u’]
c = "".join(L)

1/11 M. Rezzouk
M. Rezzouk Aide-mémoire Python

Les listes (list)

L1 = list(range(5))
L2 = ["ab"] * 5 [0, 1, 2, 3, 4] [’ab’, ’ab’, ’ab’, ’ab’, ’ab’]

L2 = list(range(2, 18, 3)) [2, 5, 8, 11, 14, 17]

L2[1:3] [5, 8, 11] (slicing ou accès par tranches)

L1 + L2 [0, 1, 2, 3, 4, 2, 5, 8, 11, 14, 17] (concaténation)

L2[-2] 14 (−1 = le dernier)

L2[::-1] toute la liste mais inversée (voir aussi .reverse())

L2.append("coucou") [2, 5, 8, 11, 14, 17, ’coucou’]


L1.extend(["coucou", "bis"]) [0, 1, 2, 3, 4, ’coucou’, ’bis’]

L2.insert(2, 'salut') [2, 5, ’salut’, 8, 11, 14, 17, ’coucou’]

a vaut 5 et L2 vaut [2, ’salut’, 8, 11, 14, 17, ’coucou’]


a = L2.pop(1)
pop() enlève le dernier élément en O(1) (structure de pile)

print(14 in L2) True

len(L2) longueur de la liste L2

for i, element in enumerate(L):


print(i, element) assez pratique pour décrire i, L[i]...

from copy import deepcopy, copy


L = [[1, 2], [3, 4]]
L2 = deepcopy(L) copie profonde (intégrale) d’une liste de liste (comparer L2 et L3)
L3 = copy(L)
L[1][1] = 2015

Les dictionnaires (dict)

dico = {"p1": 123, "p2": 34, "p3": 5}


# ou bien définitions équivalentes
dico = dict(p1=123, p2=34, p3=5)

dico["p4"] = "coucou"
del dico["p4"] une dictionnaire est modifiable, comme une liste

"p1" in dico True

2/11 M. Rezzouk
M. Rezzouk Aide-mémoire Python

for cle in dico:


print(cle, end=" ") p1 p2 p3

Les chaînes de caractères (str)

s1 = "bonjour"
s2 = " tout le monde" "bonjour tout le monde"
s = s1 + s2

L = s.split(" ") [’bonjour’, ’tout’, ’le’, ’monde’]


news = s.replace(" ", ";") ’bonjour;tout;le;monde’
' bla bla bla \n'.strip() ’bla bla bla’

c = "**".join(L) "bonjour**tout**le**monde"
"{1}--{0}**{2}".format(s1,s2,"aa") " tout le monde--bonjour**aa"

print("{:.2f}".format(1/3)) "0.33" Deux chiffres après la virgule

Opérations binaires

a | b ou binaire
a & b et binaire
a ^ b xor binaire
~a inversion de bits
a << 2 décalage de 2 vers la gauche (donc ×4)
b >> 3 décalage de 3 vers la droite
a = 0xef a réfère à l’entier écrit en hexadécimal EF (239)

L est une liste d’entiers correspondants aux octets de la chaîne


L = list(bytes("coucou", 'latin-1'))
"coucou", encodage latin-1

chaine = str(bytes(L), 'latin-1') on reconvertit en chaîne de caractères la liste L (bytes est le type
octet en Python)

Boucles, tests

while condition:
instruction() boucle tant que
else: else optionnel, si sortie propre sans break
pass

for i in liste:
instruction() boucle pour que

continue passe à l’itération suivante


break sort de la boucle

if condition:
instruction()
elif condition2: test, elif et else optionnelles
instruction2() 0 ” ou None compte pour False dans condition
else:
instruction3()

3/11 M. Rezzouk
M. Rezzouk Aide-mémoire Python

Fonctions

def fonction(a, b=2):


if b == 2:
définition d’une fonction, b est une entrée optionnelle, si elle est
return "valeur par défaut"
absente elle vaut 2
else
return a + b

pass instruction vide


return None retour « vide »

lambda x,y: x+y fonction anonyme (x, y) 7→ x + y

def f(a):
a = 2
return a
def g(a): Subtilité des références. Voici une exemple de résultat1 2 10455040
a[0] = 2
return a
10455072
a = 1
[2] [2] 139949430437384 139949430437384
b = f(a)
Traceback erreur...
print(a , b, id(a), id(b))
TypeError : ’tuple’ object does not support item assignment Par
# attention a = référence (pointeur)
a = [1]
b = g(a) ailleurs la priorité pour reconnaître une variable locale est
print(a , b, id(a), id(b)) def. locale puis on remonte la hiérarchie des fonctions. On peut
# problème tuple non modifiable comme str utiliser les mots-clé global ou non local
a = (1, )
b = g(a)
print(a , b, id(a), id(b))

def exemple(objet, *uplets, **dico): Plus élaboré, pour aller plus loin...
print("L'objet est", objet)
for a in uplets:
print(a) L'objet est bonbon
print("#" * 20) au caramel
for kw in dico: au beurre salé
print(kw, ":", dico[kw]) ####################
exemple('bonbon', 'au caramel', prix : cher
'au beurre salé', qualite : bonne
qualite = 'bonne', prix='cher')

Aller à l’essentiel (exceptions)


Python Explications
try:
c = a/b on effectue les instructions dans try et on traite les
except ZeroDivisionError: exceptions si elles sont soulevées (TypeError, NameError,
print("problème de division par 0") ZeroDivisionError, IOError...)

Les modules, fonctions courantes

import numpy as np on peut utiliser np.sin(1) par exemple à éviter mais permet de
from numpy import * taper sin(1) directement

4/11 M. Rezzouk
M. Rezzouk Aide-mémoire Python

math, os (fonctions systèmes), time, random, copy


(pour copier des listes en profondeur), numpy (ana-
lyse numérique contient d’ailleurs numpy.random),
matplotlib (plot), scipy (calcul scientifique, al- modules courants
gèbre linéaire, imagerie), sympy (calcul formel),
httplib (gestion http), tkinter (interface gra-
phique rapide)...

Manipulation de fichiers
ouverture d’un fichier : r lecture, w écriture, a écriture en ajout, b
monfichier = open("toto.txt", "r")
binaire help(file) pour les détails

for ligne in monfichier:


traitement... on parcourt les lignes

touttxt = monfichier.read() tout le texte


ligne = monfichier.readline() la ligne courante
lignes = monfichier.readlines() liste de toutes les lignes
next(monfichier) ligne suivante (monfichier est vu comme un itérable)

monfichier.write("text à écrire") ordre d’écriture

monfichier.close() fermeture (et éventuellement écriture réelle) du fichier

Calcul numérique Numpy, probabilités

np.array([1, 5, 7])
np.arange(deb, finnonincluse, increment) tableaux (array) de subdivision
np.linspace(deb, fin, nbpoints)

np.vectorize(f) permet d’utiliser la fonction scalaire f avec des array

M = np.array([[1.5, 2.1], [3.7, 4.9]]) matrice 2 × 2 (type ndarray)


M = np.array([[1, 2], [3, 4]], dtype=int) matrice 2 × 2 (cellule de type int)
dimi, dimj = M.shape renvoie la taille de la matrice (attention .size renvoie le nombre
M.reshape(4) total de cellules
M = np.zeros((a, b)) # voir aussi np.eye création d’une matrice de zéros de taille (a, b)
M[0, :] 1ère ligne de M
M[:, 1] 2e colonne de M
M * M le produit terme à terme
np.dot(M, N) # ou M.dot(N) le vrai produit matriciel MṄ
M.T la transposée de M
M.sum() somme de tous les éléments de M
v.T * w # ou np.vdot(v, w) produit scalaire (u|v)
np.cross(v, w) produit vectoriel u ∧ v
np.linalg.solve(A, V) résolution d’un système linéaire AX = V (voir l’aide)
N = M.copy() copie de M (si les coefficients sont des nombres)
M = np.concatenate([L1, L2]) concatène les lignes (attention une seule entrée)
M = np.concatenate([C1, C2, C3], axis=1) concatène les colonnes

5/11 M. Rezzouk
M. Rezzouk Aide-mémoire Python

import numpy.linalg as lg
lg.det(M) déterminant
lg.inv(M) inverse de la matrice
valeurspropres, P = lg.eig(M) valeurs propres et matrice de passage (diagonalisation) spectre de
valeurspropres = lg.eigvals(M) la matrice

for lig_idx, ligne in enumerate(M):


print("lig_idx", lig_idx, pour parcourir un tableau par ligne
"ligne", ligne)

from numpy import random


M = random.rand(5, 5) tirage uniforme dans [0,1] dans une matrice 5 × 5

import random tirage équiprobable dans [[2, 5]], attention les fonction randint de
a = random.randint(2, 5) numpy.random et de random sont légèrement différentes (bornes
b = np.random.randint(2, 6) sup exclues pour numpy.random)

import numpy.random as rd
rd.random(nbtirages)
rd.randint(a, b, nbtirages) # b exclu lois usuelles de probabilités, nbtirages est optionnel, il peut-être
rd.binomial(n, p, nbtirages) un tuple, par exemple (n, m) pour une matrice n × m.
rd.poisson(l, nbtirages)
rd.geometric(p, nbtirages)

import math
import scipy.special as s
math.factorial(n) factorielle et combinaison de Pascal (sous scipy le nombre est un
s.factorial array).
s.comb(n, k)

data = np.genfromtxt('fichier.csv', extrait les données d’un fichier .csv avec le délimiteur "," et le met
delimiter=',') dans une matrice
data = np.load("fichier.npy") idem mais en binaire, format spécial numpy en binaire

np.save("fichiersav.npy", M)
sauvegarde du tableau M dans un fichier en binaire
np.savetxt("fichiersav.csv", M,
sous la forme d’un fichier .csv par exemple
fmt='%.5f', delimiter=',')

Polynômes (numpy.Polynomial)

from numpy.polynomial import Polynomial


p = Polynomial([3, 5, -6])
p(8)
p.coef # [i] etc.
p.degree() p = 3 + 5X − 6X2 . p est un objet polynôme, on peut utiliser les
p.roots() opérateurs algébriques courants et les méthodes citées
p.derive()
p.integ()
q, r = a // b, a % b

6/11 M. Rezzouk
M. Rezzouk Aide-mémoire Python

Visualisation graphique (matplotlib.pyplot)

import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 10, 101) affiche une ligne polygonale des points définis par les vecteurs x et
y = np.sin(x) y, ici on trace la courbe y = sin x
a = plt.plot(x, y)
plt.show()

plt.clf() efface la figure courante


plt.savefig("monimage.jpg") enregistre l’image dans le format voulu

import numpy as np
import matplotlib.pyplot as plt
X = np.linspace(-np.pi, np.pi, 101)
Y = np.linspace(-np.pi, np.pi, 101) affiche des lignes de niveau de la surface z = sin(x) sin(y), on peut
XX, YY = np.meshgrid(X, Y) éventuellement utiliser l’option levels=[...].
Z = np.sin(XX) * np.sin(YY)
plt.contour(XX, YY, Z)
plt.show()

from mpl_toolkits.mplot3d import Axes3D


fig = plt.figure()
ax = fig.add_subplot(111, projection="3d") (en plus de l’exemple précédent)
ax.plot_surface(X, Y, Z) affiche la surface z = sin(xy)
plt.show()

Traitement d’images (sous module de SciPy – calcul scientifique)

import matplotlib.pyplot as plt


from scipy import ndimage
image = ndimage.imread('figure_surface.png') image est un tableau où chaque élément est un nombre (niveau de
print(image.shape) gris), un triplet (RGB) ou un quadruplet (RGBA, A pour alpha
print(image) = opacité) suivant le format de l’image.
plt.imshow(image) On peut aussi utiliser le module PIL, voir TD.
plt.axis('off')
plt.show()

SciPy – calcul scientifique, intégration numérique, équations différentielles

from scipy.integrate import quad Intégration numérique


valeur, erreur = quad(np.exp, 0, 2) calcul
Z 0 de la valeur
Z 0 approchée avec estimation de l’erreur, ici
valeur, erreur = quad(np.exp, -np.inf, 0) exp(t)dt et exp(t)dt
2 −∞

from scipy.integrate import odeint


def f(y, t):
return t * np.sin(y**2) Équations différentielles
T = np.linspace(0, 5, 101) affiche la courbe de la solution de l’équation différentielle
y 0 = t sin y 2 avec y(0) = 1 sur [0, 5] pour une subdivision de

Y = odeint(f, 1, T)
plt.plot(T, Y) 100 + 1 éléments. Attention y 0 = f (y, t) et non pas f (t, y).
plt.show()

7/11 M. Rezzouk
M. Rezzouk Aide-mémoire Python

def f(a, t, y):


return [y[1],
-a*y[1] - y[0] + 0.1*np.cos(t)]
y0, t0, t1, n = [1, 0], 0, 30, 201 Équations différentielles ordre 2, système différentiel
T = np.linspace(t0, t1, n) affiche les courbes de la solution de l’équation différentielle
for i in range(1, 7): y 00 = −ay 0 − y + 0.1 cos(t) avec y(0) = 1 et y 0 (0) = 0 sur [0, 30]
Y = sc.odeint(lambda y, t: f(i, t, y), pour une subdivision à 201 éléments avec a ∈ 1, ..., 7
y0, T)
plt.plot(T, Y[:, 0], linewidth=2)
plt.show()

from numpy import sin


from scipy.optimize \
import bisect, fsolve, root
racine = bisect(sin, 3, 4)
racine2 = fsolve(sin, 3.) Racines f (x) = 0
Résolution de sin(x) = 0 pour x ∈ [3, 4] par dichotomie.
def f(v): avec fsolve autour de 3
return v[0]**2-v[1]**2-1, 2*v[0]+v[1]-5 Pour les systèmes (non linéaires) on peut utiliser root ou fsolve
Il existe aussi la fonction newton...
sol = root(f, [-5, 5])
sol.success # True ou False
sol.x # solutions
sol2 = fsolve(f, [-5, 5])

Classes, objets, attributs, méthodes

class Personne(object):
nbpersonne = 0 # var. statique
def __init__(self, nom, prenom, age):
self.nom = nom
self.prenom = prenom
self.age = age
Personne.nbpersonne += 1
def __repr__(self): Programmation orientée objet.
return "{} {}".format( Résultat
self.prenom.capitalize(),
self.nom.capitalize()) Robert Dupont Nb personnes : 2
def nbpers(self):
return Personne.nbpersonne

lui = Personne("durand", "robert", 35)


elle = Personne("lefevre", "julie", 35)
lui.nom = "dupont"
print(lui, "Nb personnes:", lui.nbpers())

8/11 M. Rezzouk
M. Rezzouk Aide-mémoire Python

Divers
exécuté dans le module, permet de tester les fonctions documenté
par exemple
import doctest
if __name__ == '__main__': ''' fonction renvoie3
test() >>> renvoie3()
doctest.testmod() 3
'''

aide sur une fonction, un module.


help(print)
Utiliser l’aide en ligne ou l’inspecteur d’objets (sous Spyder)

Base de données – SQL


Vocabulaire des bases de données
Bases de données : vocabulaire
eleves profs
id nom prenom id nom prenom
0 Lions Jacques-Louis 0 Théron Pierre
1 Laurent Jean 1 Brun Jules
... ... ... ... ... ...

colles
prof eleve semaine note
2 8 1 16
1 0 6 19
... ... ... ...

• Relation, table, base, schéma relationnel = ensemble d’attributs


• Colonne = champ = attribut dans un domaine bien défini
• Ligne = enregistrement = tuple (ou un dictionnaire python ?)
• Clé (primaire/étrangère), jointure
• (Fonction d’) agrégation (COUNT, SUM, ADD...)
• Algèbre relationnelle (mise sous forme algébrique d’une requête)

Memento SQL
Éléments de SQL
(sigle de Structured Query Language, en français langage de requête structurée)
Optionnel
CREATE TABLE ... et INSERT INTO ...

Requêtes

• Projection π... () , sélection σ... ()


SELECT ... FROM ... WHERE ...
• Renommage ρchamp1→taille (...)
SELECT champ1 [AS] taille ...
• Produit caratésien t1 × t2
On peut effectuer le produit cartésien en listant les tables
SELECT ... FROM t1, t2 WHERE ...
• Jointures (symétriques) t11 t2
C

SELECT ... FROM t1 JOIN t2 ON C WHERE ...


ou encore
SELECT ... FROM t1 JOIN t2 JOIN t3 ON t1.a1 = t2.a1 AND t2.b3 = t3.c5 WHERE ...

9/11 M. Rezzouk
M. Rezzouk Aide-mémoire Python

• Agrégats   
πchamp,COUNT(champ) σcondition champ γCOUNT(champ) (table)

Ils utilisent les fonctions COUNT(), COUNT(DISTINCT ...), SUM(), MAX(), MIN(), AVG()... SELECT champ, COUNT(...)
FROM table WHERE condition GROUP BY champ
COUNT(*), * = joker
On peut rajouter une condition sur les groupes avec HAVING, par exemple
SELECT groupe_colle FROM eleves
GROUP BY groupe_colle
HAVING COUNT(groupe_colle) = 2
  
πgroupe_colle σCOUNT(groupe_colle)=2 groupe_colle γCOUNT(groupe_colle) (eleves)

• Particularité SQL
SELECT DISTINCT pour enlever les redondances (inexistantes en algèbre relatrionnelle)
ORDER BY à la fin pour ordonner d’une certaine manière la table (=relation) renvoyée.
Par exemple
ORDER BY note DESC, nom ASC (on trie déjà selon la note puis selon le nom)
• En résumé

SELECT [DISTINCT] attributs, fonctions d’agrégation


FROM liste de tables
[JOIN table ON conditionjointure ]
WHERE conditions
[GROUP BY liste d’attributs
HAVING conditions ]
[ORDER BY liste d’attributs [ASC ou DESC]]
[LIMIT nb]

On peut utiliser des alias pour renommer les tables, c’est parfois indispensable si on dédouble une table (on peut être
explicite en utilisant le mot-clé AS (optionnel))
• À noter : on peut utiliser des sous-requêtes entourée par des parenthèses.
Exemple

SELECT nom
FROM eleves
WHERE note =
(
SELECT MAX(note)
FROM eleves
) ;

• Un peu moins utile mais au programme


Opérations ensemblistes
◦ Union
SELECT FROM... UNION SELECT FROM...
◦ Intersection
SELECT FROM... INTERSECT SELECT FROM...
◦ Différence
SELECT FROM... EXCEPT SELECT FROM...
• Syntaxe de logique
Logique : AND, OR, NOT, <, <=, <>

Codage des nombres


Les entiers relatifs : la notation en complément à 2
Commençons par regarder le cas particulier des entiers codés sur un octet. On décide de représenter les entiers entre −128
et 127 de la manière suivante :
• si x ∈ [[0, 127]] alors x est codé par son écriture binaire sur un octet.
• si x ∈ [[−128, −1]] alors x est codé par l’écriture binaire de x + 256 sur un octet.

10/11 M. Rezzouk
M. Rezzouk Aide-mémoire Python

entier à coder

−128 −127 −1 0 1 127

0 1 127 128 255

écriture binaire
notation en complément à deux
Ainsi, on fait correspondre à chaque entier de [[−128, 127]] un entier de [[0, 255]] qui est ensuite codé sur 8 bits par sa
représentation binaire. On remarquera que 0 admet alors une seule écriture : 00000000.
On remarque que le signe d’un entier est immédiat à déterminer via sa notation en complément à deux : il est
donné par le bit de poids fort. Le nombre est positif lorsque le bit de poids fort vaut 0 et négatif sinon.
Nous pouvons maintenant généraliser à la notation en complément à deux sur n bits.
On représente les entiers entre −2n−1 et 2n−1 − 1 de la manière suivante :
• si x ∈ [[0, 2n−1 − 1]] alors x est codé par son écriture binaire sur n bits.
• si x ∈ [[−2n−1 , −1]] alors x est codé par l’écriture binaire sur n bits de x + 2n (c’est-à-dire le complémentaire de |x| plus
1 = ((2n − 1) − |x|) + 1, ce qu’on appelle le complément à 2).
Si x + y > 2n−1 ou si x + y < −2n−1 , il y a un dépassement de capacité, si x + y ∈ [[−2n−1 , 2n−1 [[, le résultat est correct.
En python 3, les type int changent de codage si le nombre augmente, il n’y a pas de dépassement de capacité.

Les flottants
Un flottant est stocké sous la forme : signe, mantisse, exposant en binaire où signe est codé par 0 pour positif et 1 pour
négatif et la mantisse et l’exposant sont codés de manière habituelle en binaire.
Un tel nombre sera stocké sur n bits avec n = 32 ou 64 en général. Supposons par exemple que l’on travaille sur 64 bits.
Le premier bit est réservé au signe puis vient la mantisse puis enfin l’exposant. Le découpage utilisé est le suivant :
signe mantisse exposant

1 0 1 1 0 1

1 bit 52 bits 11 bits

L’exposant e est en fait un entier relatif entre −1022 et 1023 qui est représenté en binaire via e + 1023 sur 11 bits (attention,
ça n’est pas le complément à deux). e + 1023 peut donc prendre les valeurs de 1 à 2046. Comme 211 − 1 = 2047, on voit qu’il
manque 0 et 2047. Ces deux valeurs sont réservées pour gérer des exceptions.
Enfin, on sait que le premier chiffre de la mantisse, par définition est 1 (sauf pour le nombre 0) donc il est inutile de le stocker
ce qui fait que l’on stocke en réalité les 52 chiffres après la virgule de la mantisse.
Remarque Cette manière de coder les flottants correspond au système de double précision. Il existe aussi un système
à simple précision où les nombres sont codés sur 32 bits. Comme on le verra, sur 64 bits, on obtient environ 16 chiffres
après la virgule (dans la notation décimale) alors que sur 32 bits, on obtient 8 chiffres après la virgule.
On retiendra que pour des flottants en précision 64 bits, l’approximation relative d’un réel ne dépasse jamais ε = 10−16 .

Il reste ensuite à coder quelques cas qui peuvent se produire dans des calculs numériques comme les dépassements, les
divisions par zéro ou encore la gestion des nombres dénormalisés (c0 = 0). Tout ceci est fait en utilisant les exposants codés
en 00000000000 ou 11111111111.
• Plus précisément
0 0...0 11111111111 = +∞
1 0...0 11111111111 = −∞
0 ou 1 puis 52 bits non tous nuls puis 11111111111 = NaN Not a Number
• Lorsque l’exposant est 00000000000 mais que la mantisse est non nulle, on considère que le premier chiffre avant la virgule
est 0 et que l’exposant est −1022 (et non pas −1023). Ces nombres sont dits dénormalisés. Ils permettent une meilleure
répartition des (très) petits nombres représentables.

11/11 M. Rezzouk

Vous aimerez peut-être aussi