Pour n=30, voilà les valeurs successives de la liste s après l’itération “pour p”:
# Liste s initiale
s =
[0,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]
# La liste s à la fin de chaque itération de la boucle “pour p”
p = 2, s=[0,1,2,3,0,5,0,7,0,9,0,11,0,13,0,15,0,17,0,19,0,21,0,23,0,25,0,27,0,29,0]
p = 3, s=[0,1,2,3,0,5,0,7,0,0,0,11,0,13,0,0,0,17,0,19,0,0,0,23,0,25,0,0,0,29,0]
p = 4, s est inchangée car s[4] = 0
p = 5, s=[0,1,2,3,0,5,0,7,0,0,0,11,0,13,0,0,0,17,0,19,0,0,0,23,0,0,0,0,0,29,0]
# Et l’extraction finale des entiers > 1 de s qui sont les nombres premiers b 30
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
Q1) Ecrire une fonction crible(n) (avec n entier) calculant la liste des nombres premiers inférieurs ou égaux à n. Tester.
3) Calcul de la liste des valeurs de la fonction g: première idée
On veut calculer la liste val_g
n
=
g
4
,g
6
,g
8
, ..., , g
2n
.
Il faut commencer par calculer la liste s = crible(2n) des nombres premiers b 2n.
Notons s=
2, 3, 5 ..., p
-
= [s[0],s[1],...,s[ns-1]] la liste des nombres premiers inférieurs ou égaux à 2n. Par définition de
,
est le nombre de couples
s
i
,s
j
de la liste s qui vérifient
et s
i
+s j
=2k. La première idée qui vient
est donc de coller à la définition en calculant g
2k
pour kœ
1, n
.
fonction val1_g(n):
s = crible(2n)
ns = len(s)
res = ? # Initialisation de la liste res=[g(4), g(6),...,g(2n)]
pour k variant de 1 à n: # On va calculer g(2k)
calculer le nombre NC de couples (s[i], s[j]) de la liste s qui vérifient
0bjbibns -1 et s[i]+s[j]=2k et placer NC au bon endroit dans res
résultat = res
Q2) Ecrire une fonction val1_g(n) (avec n entier) calculant la liste des nombres premiers inférieurs ou égaux à n.
Tester, on doit trouver val1_g(15) = [1, 1, 1, 2, 1, 2, 2, 2, 2, 3, 3, 3, 2, 3]
4) Limites de cette première version du calcul des valeurs de g
La fonction ci-dessous permet de calculer la durée d’exécution de f(n), avec f fonction quelconque
import time
def duree(f, n):
""" durée d'exécution de f(n)"""
t = time.perf_counter()
f(n)
t = time.perf_counter() - t
rep = "Durée d'exécution de {0}({1}) = {2:.3g} s".format(f.__name__,n, t)
print(rep)
Q3) Calculer les durées avec f = va11_g et n = 100, 500, 1000: la patience est déjà mise à rude épreuve. Essayons d’évaluer la
complexité de cette fonction val1_g. L’instruction “if s[i]+s[j] == 2k:” est au cœur des trois boucles, comptons le nombre
N de fois qu’elle est exécutée. On a: N= S
k=
S
i=
-
S
j=
1 = S
=
S
i=
-
i+1
= S
=
ns
ns+1
=
n-1
*
. Or (on l’admet),
ns ~
n
~
n
, Donc N~
n*
2n
n
2
=O
n
2
n
. Si l’on note
n
=
n
2
n
, alors
1000
f
100
º444: il faut en théorie
444 fois plus de temps pour avoir la réponse de val1_g(n) quand on passe de n=100 à n=1000. Vérifier que ce calcul théorique
est validé par les temps de calculs faits ci-dessus. Il faut trouver une autre idée pour calculer g.
TP - Conjecture de Goldbach.nb 2/3