Première version :
def Eratosthene(N):
# renvoie la liste des premiers entre 2 et N-1
liste= [x for x in range(2,N)]
premiers= []
while len(liste) > 0 :
p= liste[0]
premiers.append(p)
liste= [x for x in liste if x%p != 0]
return premiers
print(Eratosthene(100))
%time L= Eratosthene(20000)
Tentative pour accélérer :
def Eratosthene2(N):
liste= [x for x in range(2,N)]
premiers= []
while len(liste) > 0 :
p= liste[0]
premiers.append(p)
x= p
while x < N:
if x in liste:
liste.remove(x)
x= x+p
return premiers
%time L= Eratosthene2(20000)
En fait c'est bien pire -- l'intention est bonne, mais la construction des listes en Python est trop lente.
Voici la version ultime :
def Eratosthene3(N):
table= [True for x in range(N)] # table = [True, True, True, ...]
p= 2
while p < N:
# on met "False" pour tous les multiples de p
i= p + p # i= 2*p
while i < N:
table[i]= False
i= i+p
# on cherche le prochain nombre premier
p= p+1
while p < N and not(table[p]):
p= p+1
return [p for p in range(2,N) if table[p] ]
%time L= Eratosthene3(20000)
292/14.0
On a accéléré 20 fois environ.
On fait une fonction auxiliaire :
def bezout_aux(x, y, ux, vx, uy, vy):
if y == 0:
return [x, ux, vx]
else:
print("On va maintenant calculer le pgcd de", x, "et", y)
q= x//y
r= x%y
print("On a fait la division euclidienne", x, "=", y, "*", q, "+", r)
print("et le reste s'exprime comme", r, "= a*",ux - q*uy , "+ b*", vx - q*vy )
return bezout_aux(y, r, uy, vy, ux - q*uy, vx - q*vy)
dans laquelle $x, y, u_x, v_x, u_y, v_y$ sont des entiers. On suppose qu'il existe $a$ et $b$ non donnés tels que
$x = a u_x + b v_x$
$y = a u_y + b v_y$
La fonction bezout_aux(x, y, ux, vx, uy, vy) renvoie $[d, u, v]$ où $d$ est le pgcd de $x$ et $y$, et
$d = au + bv$.
Ensuite on fait:
def bezout(a, b):
return bezout_aux(a, b, 1, 0, 0, 1)
Notes sur le fonctionnement de bezout_aux
.
On note que si $y=0$, alors $pgcd(x,0) = x$ et $x = au_x + bv_x$ donc on renvoie $(x, u_x, v_x)$ dans ce cas.
Sinon on écrit $x= yq + r$ (division euclidienne)
Alors $pgcd(x, y) = pgcd(y, r)$ et $$r = x - yq = au_x + bv_x - q(au_y + bv_y) = a(u_x - q u_y) + b(v_x - q v_y)$$
Donc dans ce cas on renvoie bezout_aux(y, r, uy, vy, ux - quy, vx - qvy)
bezout(24, 15)
Première version :
def stirling(n,k):
if n==0 or k==0:
if n==k:
return 1
else:
return 0
return (n-1)*stirling(n-1,k) + stirling(n-1,k-1)
%time stirling(50, 6)
Voyons la version avec un dictionnaire. On commence par un dictionnaire vide :
table_stirling= {}
Et on stocke les résultats dedans au fur et à mesure, comme ceci :
def stirling2(n,k):
# petites valeurs :
if n==0 or k==0:
if n==k:
return 1
else:
return 0
# sinon :
if (n,k) in table_stirling:
return table_stirling[(n,k)]
else:
valeur= (n-1)*stirling2(n-1,k) + stirling2(n-1,k-1)
table_stirling[(n,k)]= valeur
return valeur
Une petite fonction pour afficher joliment le dictionnaire :
def triangle():
ns= [n for n,k in table_stirling]
if len(ns) == 0:
print("<table vide>")
return
N= max(ns)
if N > 50:
print("on affiche seulement les 50 premières lignes")
N= 50
for n in range(N+1):
if n not in ns:
continue
print(n, "|", end=" ")
ks= [k for a,k in table_stirling if a==n]
h= max(ks)
for k in range(1,h+1):
if k in ks:
print(table_stirling[(n,k)], end=" ")
else:
print("?", end= " ")
print()
Et maintenant essayons :
triangle()
stirling2(7,4)
%time stirling2(50,6)