• Aucun résultat trouvé

L3 Informatique MPI4 – TD 8 : Nombres premiersPremiers pas.

N/A
N/A
Protected

Academic year: 2022

Partager "L3 Informatique MPI4 – TD 8 : Nombres premiersPremiers pas."

Copied!
4
0
0

Texte intégral

(1)

L3 Informatique MPI4 – TD 8 : Nombres premiers

Premiers pas.

Écrire une fonction primes(n) retournant la liste des nombres premiers inférieurs à . On pourra utiliser le crible d'Eratosthène (http://fr.wikipedia.org /wiki/Crible_d'%C3%89ratosth%C3%A8ne).

Pour trouver les nombres premiers entre 2 et , on part d'une liste pp contenant seulement 2, et d'une liste mm contenant tous les nombres entre 2 et qui ne sont pas multiple de 2. mm[0] est donc 3, qui est forcément premier puisque pas multiple des nombres premiers qui lui sont inférieurs. On fait donc passer 3 à la fin de pp et on élimine de mm tous les multiples de 3. On recommence, 5 passe dans pp et les multiples de 5 sont éliminés. A chaque étape, mm[0] est un nombre premier , on l'ajoute à pp et on élimine ses multiples de mm, jusqu'à ce que mm soit vide.

Calculer primes(10000) et comparer avec ce qu'on obtient en filtrant range(10000) avec 4 tests de Miller-Rabin.

In [1]: def primes(n):

if n<2: return []

pp = [2]; mm = [m for m in range(3,n) if m%2]

while mm:

p = mm[0]

pp.append(p)

mm = [m for m in mm[1:] if m%p]

return pp

In [2]: print (primes(100))

In [3]: # Miller-Rabin

from random import randrange def test_base(a,n):

m = n-1; k = 0 while not m%2:

k+=1; m//=2 b = pow(a,m,n) if b==1: return True for i in range(k):

x = b

b = pow(b,2,n) if b==1:

if x != n-1: return False else: return True return False

def miller_rabin(n, tests=4):

if n in [2,3]: return True if not n%2: return False for i in range(tests):

a = randrange(2,n-1)

if not test_base(a,n): return False return True

pp = primes(10000)

mr = [p for p in range(2,10000) if miller_rabin(p)]

In [4]: [q for q in mr if q not in pp]

In [5]: miller_rabin(1729, tests=4)

n

n n

p

[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]

Out[4]: []

Out[5]: False

mpi4_td8_2020-sol_py3 http://www-igm.univ-mlv.fr/~jyt/L3_MPI4/mpi4_...

1 sur 4 10/12/2020 10:56

(2)

Factorisation

Force brute

Pour factoriser , précalculer une liste des premiers nombres premiers, tester s'ils divisent , et répéter récursivement sur le quotient. Si est le dernier de la liste et , c'est fini, sinon il faut continuer : tester les facteurs jusqu'à ce que . On pourra écrire une fonction intermédiaire trial_division(n) qui retourne le premier diviseur rencontré. Est-il nécessairement premier ?

Force brute améliorée

On se contente de la liste [2,3,5] et on repart de 7. On a , et si le facteur testé n'est pas congru à 1 ou à un nombre premier modulo 30, alors et il ne peut pas être premier. On incrémentera donc de 4,2,4,2,4,6,2,6 (périodicité 8) de manière à ce que soit successivement 11,13,17,19,23,29,1,7. Comparer les temps d'exécution des deux méthodes.

In [7]: def trial_division(n):

if n == 1: return 1 if n%2 == 0: return 2 if n%3 == 0: return 3 if n%5 == 0: return 5 if n<30: return n p = 7

while p*p <= n:

if n%p == 0: return p p +=2

return n

In [8]: def F(n):

return 2**(2**n)+1 print (F(6))

print (trial_division(F(6)))

In [9]: def trial_division(n, bound=None):

if n == 1: return 1 for p in [2, 3, 5]:

if n%p == 0: return p if bound == None: bound = n dif = [6, 4, 2, 4, 2, 4, 6, 2]

m = 7; i = 1

while m <= bound and m*m <= n:

if n%m == 0:

return m m += dif[i%8]

i += 1 return n def factor(n):

if n in [-1, 0, 1]: return []

if n < 0: n = -n F = []

while n != 1:

p = trial_division(n) e = 1

n //= p while n%p == 0:

e += 1; n //= p F.append((p,e)) F.sort()

return F

In [10]: factor(F(5))

In [11]: factor(F(6))

n M n p

np2 fk=p+ 2k nfk2

2 × 3 × 5 = 30 f

f∧ 30 ≠ 1 f f mod 30

18446744073709551617 274177

Out[10]: [(641, 1), (6700417, 1)]

Out[11]: [(274177, 1), (67280421310721, 1)]

mpi4_td8_2020-sol_py3 http://www-igm.univ-mlv.fr/~jyt/L3_MPI4/mpi4_...

2 sur 4 10/12/2020 10:56

(3)

Test de Lucas

C'est la réciproque du théorème de Fermat. On rappelle que ce dernier est un cas particulier du théorème de Lagrange : dans un groupe fini, l'ordre de tout élément est un diviseur de l'ordre du groupe. Ainsi, si est premier, est un corps, et son groupe multiplicatif est d'ordre . Mais si n'est pas premier, l'ordre de ce groupe est strictement inférieur à . Donc, si on peut trouver un élément a d'ordre exactement n−1, n sera nécessairement premier.

Pour appliquer cette idée, on factorise pour avoir la liste de ses diviseurs premiers. On calcule ensuite pour diverses valeurs de telles que , les pour tous les . Si pour un certain a aucun n'est égal à 1, on a la preuve que n est premier.

In [12]: def lucas(n, tests=4):

bases = [randrange(2,n-1) for i in range(tests)]

for a in bases:

if pow(a,n-1,n) != 1: return False # n n'est pas permier Q = [x[0] for x in factor(n-1)]

for a in bases:

if all([(pow(a,(n-1)//q,n) != 1) for q in Q]):

return True # n est premier

return 'FAIL' # On ne peut pas conclure, il faut d'autres essais

In [13]: n = 2**107-1 lucas(n)

In [14]: lucas(F(4))

Test de Lucas-Lehmer.

Il permet de savoir si un nombre de Mersenne (https://fr.wikipedia.org/wiki/Nombre_de_Mersenne_premier) est premier. Voir là (https://en.wikipedia.org /wiki/Lucas–Lehmer_primality_test) pour les détails.

Pour prouver que est premier, on suppose qu'il possède un diviseur premier avec . Le groupe des éléments inversibles de est d'ordre au plus . Si on peut trouver un élément d'ordre supérieur à celui de ce groupe, cela prouvera qu'un tel n'existe pas.

Soient et . On a , et la suite vérifie et . Si on suppose que , on a

donc

donc , d'où

et

Ainsi, est d'ordre dans . Comme l'ordre de est , c'est impossible.

Donc, si , alors est premier.

Le plus grand nombre premier connu (https://primes.utm.edu/largest.html#largest) est en général un nombre de Mersenne.

In [15]: def lehmer(p, verbose=False):

assert miller_rabin(p) M = pow(2,p)-1 s = 4

for i in range(p-2):

u,s = s, (s*s-2)%M if s%M == 0:

if verbose: print ('M(%d) = (%d) est premier' % (p,M)) return True

else:

if verbose: print ('M(%d) = (%d) est composé' % (p,M)) return False

In [16]: n=2**107-1;n

In [17]: lucas(n,tests=8)

n Z/nZ n− 1 n

n− 1

n− 1 Q a

≡ 1 mod n

an−1 a(n−1)/q mod n qQ

= − 1

Mp 2p q q2Mp G

[ ]

Zq√3– q2− 1 ≤2p− 2 a q

z= 2 + 3–√ z¯= 2 −√3– zz¯= 1 sn=z( )2n +z¯( )2n s0= 4 sn=s2n−1− 2 Mp|sp−2

+ =k

z(2p−2) z¯(2p−2) Mp

=k − 1

z(2p−1) Mpz(2p−2)

≡ −1 mod q z(2p−1)

≡ 1 mod q z( )2p

z 2p G G <2p− 2

|

Mpsp−2 Mp Out[13]: True

Out[14]: True

Out[16]: 162259276829213363391578010288127

Out[17]: True

mpi4_td8_2020-sol_py3 http://www-igm.univ-mlv.fr/~jyt/L3_MPI4/mpi4_...

3 sur 4 10/12/2020 10:56

(4)

In [18]: lehmer(107)

In [ ]: lehmer(107,verbose=True)

In [ ]: mm = [p for p in pp if lehmer(p)]

In [ ]: print (mm)

In [ ]:

In [ ]:

Out[18]: True

M(107) = (162259276829213363391578010288127) est premier Out[ ]: True

mpi4_td8_2020-sol_py3 http://www-igm.univ-mlv.fr/~jyt/L3_MPI4/mpi4_...

4 sur 4 10/12/2020 10:56

Références

Documents relatifs

Arithmétique (nombres premiers et premiers jumeaux ), tests de primalité, fonctions renvoyant une valeur booléenne, test dans une boucle avec une fonction booléenne, liste, ajouter

C'est Euler qui, longtemps avant Ulam, trouva cette suite de nombres premiers, comme images d'entiers consécutifs par le polynôme P (x )=x 2 −x + 41. Si on calcule ces images avec un

On s'intéresse à la répartition des nombres premiers dans l'ensemble des entiers naturels. On prendra soin d'inclure un compteur pour donner le nombre de nombres premiers de la liste

La tangente de l’angle  est encore un troisième rapport de deux longueurs : celle du côté opposé à l’angle  et celle du côté adjacent... Il y a 4 nombres trigonométriques

Il y a plusieurs unités possibles (plusieurs dénominateurs communs), choisir le plus grand possible (donc le plus petit dénominateur commun) permet de rendre plus simple le calcul

Elle veut utiliser tous les bonbons, pour r´ealiser des petits paquets ayant tous le mˆ eme contenu.. Quel est le plus grand nombre de paquets qu’elle

La commande input permet à l'utilisateur de rentrer des valeurs en argument dans un programme sans avoir à dénir une fonction.. Par exemple, x = input(&#34;rentrer x&#34;) ache

2- Observe chaque suite et complète.. Écris le titre sur