Dans ce TP, on s'intéresse aux nombres premiers, à leur identification et leur recherche.
On rappelle la définition d'un nombre premier : il s'agit d'un entier naturel qui possède deux diviseurs distincts : 1 et lui-même.
En conséquence le nombre 1 n'est pas premier car il ne possède qu'un seul diviseur.
La liste des premiers nombres premiers est : 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, ...
On désire écrire une fonction en Python qui accepte un argument entier et qui permet de déterminer si un nombre est premier ou non.
On renverra True
si le nombre est premier, sinon on renverra False
On va par la suite écrire plusieurs versions.
Dans un premier temps, on détermine si un nombre est premier ou non en comptant son nombre de diviseurs.
Voici l'algorithme de la fonction à implanter :
fonction est_premier(n) | |
---|---|
Entrée | n (entier) : nombre pour lequel on doit déterminer s'il est premier ou non |
Sortie | booléen, vrai si n est premier, faux sinon |
Variableslocales | nbr_diviseurs (entier) : compte le nombre de diviseurs de n |
Description |
On calcule le nombre de diviseurs de n, s'il en existe deux alors le nombre est premier |
|
La seule difficulté rencontrée consiste à déterminer si $i$ est un diviseur de $n$ :
Pour trouver le reste de la division, on utilise l'opération modulo : $n\ %\ i$
Exercice 3.1
Ecrire le programme
En résultat on affichera, la liste des nombres premiers et la somme des nombres de la liste.
python3 python3 nombres_premiers_compte_diviseurs.py 100
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
1,060
Exercice 3.2
Mettre en commentaire l'affichage de la liste des nombres premiers.
Calculez le temps d'exécution pour la recherche des nombres premiers entre 1 et 20000 en utilisant la
commande
Voici le résultat sur AMD Ryzen 5 5600G :
\$ time python3 nombres_premiers_compte_diviseurs.py 20000
sum = 21,171,186
real 0m5,704s
user 0m5,694s
sys 0m0,008s
La version précédente n'est pas efficace pour plusieurs raisons :
Prenons un exemple ($n = 37$) pour comprendre pourquoi il ne faut pas aller au-delà de $√(37)+1$
diviseurs | quotient | reste |
1 | 37 | 0 |
2 | 18 | 1 |
3 | 12 | 1 |
4 | 9 | 1 |
5 | 7 | 2 |
6 | 6 | 1 |
7 | 5 | 2 |
8 | 4 | 5 |
9 | 4 | 1 |
10 | 3 | 7 |
etc | etc | etc |
Au-delà de 7 les quotients seront nomarlement inférieurs à 7, or on a déjà testé les diviseurs de 1 à 7.
Voici l'algorithme de la fonction est_premier basée sur le calcul du nombre de divisieurs.
Fonction est_premier(n) | |
---|---|
Entrée | n (entier) : nombre pour lequel on doit déterminer s'il est premier ou non |
Sortie | booléen, vrai si n est premier, faux sinon |
Description | On cherche les diviseurs impairs de 3 à $√(n)+1$ |
|
L'implantation en Python pose un seul problème lié à la racine carrée car elle fait partie des calculs sur les nombres réels :
Exercice 3.3
Ecrire le programme
Tout comme dans le programme précédent, en résultat on affichera la somme des nombres de la liste.
Exercice 3.4
Calculez le temps d'exécution pour la recherche des nombres premiers entre 1 et 20000 en utilisant la commande
Que remarquez vous ?
Une autre solution, plutôt que de déterminer si un nombre $n$ est premier,
consiste à utiliser un tableau de booléens
Pour remplir le tableau, on procède ainsi :
fonction | |
---|---|
Description | remplir un tableau et éliminer les multiples |
|
Exercice 3.5
Ecrire le programme
Tout comme dans le programme précédent, en résultat on affichera la somme des nombres de la liste.
Exercice 3.6
Calculez le temps d'exécution pour la recherche des nombres premiers entre 1 et 20000 en utilisant la commande
S'il vous reste du temps...
On appelle suite de Collatz (Lothar Collatz), une suite de nombres générée par la fonction de Collatz appliquée récursivement à partir d'un entier naturel $n$.
La fonction de Collatz est une fonction récursive applicable à tout entier positif $n$, définie par :
La conjecture de Collatz, ou conjecture de Syracuse, énonce qu'une suite de Collatz se termine par $1$.
Exercice 3.7
Ecrire le programme
On testera pour $n = 27$.
[27, 82, 41, 124, 62, 31, 94, 47, 142, 71, 214, 107, 322, 161, 484, 242, 121, 364, 182, 91, 274, 137, 412, 206, 103, 310, 155, 466, 233, 700, 350, 175, 526, 263, 790, 395, 1186, 593, 1780, 890, 445, 1336, 668, 334, 167, 502, 251, 754, 377, 1132, 566, 283, 850, 425, 1276, 638, 319, 958, 479, 1438, 719, 2158, 1079, 3238, 1619, 4858, 2429, 7288, 3644, 1822, 911, 2734, 1367, 4102, 2051, 6154, 3077, 9232, 4616, 2308, 1154, 577, 1732, 866, 433, 1300, 650, 325, 976, 488, 244, 122, 61, 184, 92, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1]
Cette suite comporte 112 termes.
Attention, il faut utiliser la division entière : //
.