Inscription / Connexion Nouveau Sujet
Niveau terminale
Partager :

Algorithme de factorisation

Posté par
Dactyle
02-01-14 à 21:27

Bonjour,

Je dois réaliser un algorithme avec Algobox pour factoriser un entier en deux facteurs premiers. J'en ai fait un qui fonctionne pour des nombres jusqu'à 5 chiffres mais qui se bloque pour des plus grands nombres à cause d'un "dépassement de la capacité autorisée pour les boucles"... Sauf qu'en particulier je suis censé factoriser 406421 : trop grand pour mon algorithme ):

Voici l'algorithme :

1   VARIABLES
2     m EST_DU_TYPE NOMBRE
3     p EST_DU_TYPE LISTE
4     i EST_DU_TYPE NOMBRE
5     j EST_DU_TYPE NOMBRE
6   DEBUT_ALGORITHME
7     LIRE m
8     POUR i ALLANT_DE 2 A m
9       DEBUT_POUR
10      p[i] PREND_LA_VALEUR i
11      FIN_POUR
12    POUR i ALLANT_DE 2 A sqrt(m)
13      DEBUT_POUR
14      SI (p[i]!=0) ALORS
15        DEBUT_SI
16        j PREND_LA_VALEUR i
17        TANT_QUE (j<=m) FAIRE
18          DEBUT_TANT_QUE
19          j PREND_LA_VALEUR j+i
20          p[j] PREND_LA_VALEUR 0
21          FIN_TANT_QUE
22        FIN_SI
23      FIN_POUR
24    POUR i ALLANT_DE 2 A m
25      DEBUT_POUR
26      POUR j ALLANT_DE i A m
27        DEBUT_POUR
28        SI (p[i]*p[j]==m et p[j]!=0 et p[i]!=0) ALORS
29          DEBUT_SI
30          AFFICHER p[i]
31          AFFICHER "*"
32          AFFICHER p[j]
33          AFFICHER "="
34          AFFICHER m
35          FIN_SI
36        FIN_POUR
37      FIN_POUR
38  FIN_ALGORITHME

Quelqu'un aurait-il une solution pour réduire le nombre de boucles de mon algorithme ou un coup de main pour factoriser ce foutu nombre ?

Merci bien !

Posté par
ravinator
re : Algorithme de factorisation 02-01-14 à 22:34

Bonsoir,

Ton idée est pas mal : elle repose sur le crible d'Eratostène à ce que j'ai compris, mais le soucis est qu'elle est trop longue, mais l'idée est là : il faut faire une liste des nombres premiers, et regarder quel produit redonne ton nombre de départ.

Il existe des manières plus efficaces de réaliser cette liste.

Il faut pour cela implémenter un test de primalité. Je ne connais pas Algobox, mais il doit surement y avoir une commande qui te donne le reste dans la division euclidienne a de par b. Par la suite, je noterai a % b ce nombre.
Ainsi, a est divisible par b ssi a % b = 0.

Voici une implémentation simple et relativement efficace d'un test de primalité
n : entier
continue : booléen
k : entier
Saisir n
(pour accélérer un peu)

si n = 2 :
Renvoi VRAI

sinon si n % 2 = 0 :
Renvoi FAUX

sinon :
k Prend la valeur 3
continue Prend la valeur VRAI
Tant Que continue = VRAI ET k <= sqrt(n) :
si n % k = 0 :
continue prend la valeur FAUX
sinon k prend la valeur k + 2

Fin Tant Que

Renvoi continue


Maintenant, on peut insérer ce morceau au sein d'un algorithme plus grand, qui va faire la liste des nombres premiers entre 2 et m

L : Type Liste
j : type Entier (c'est l'indice de la liste, que je suppose allant de 0 à longueur_liste -1)

Pour i allant de 2 à m :
Si i est premier (donc si la fonction précédente renvoie la valeur VRAI) :

L[j] prend la valeur i
j prend la valeur j+1

Fin Pour

Ainsi, tu obtiens la liste de tous les nombres premiers susceptibles d'apparaître dans la décomposition de ton nombre

A toi maintenant d'implémenter tout ça.
Je ne sais pas me servir d'Algobox, mais j'espère que tu saisiras l'idée =)



Posté par
ravinator
re : Algorithme de factorisation 02-01-14 à 22:47

En fait, là où on perd énormément de temps, c'est sur la double boucle tant que de la fin.
En effet, une seule suffit :
Si L est la liste des entiers premiers plus petits que m, et que cette liste est de taille N, alors

Pour i allant de 0 à N-1 :
Si m % L[i] = 0 ET (m / L[i]) est Premier, alors renvoyer ( L[i] , m / L[i])

Ca permet d'économiser pas mal de temps

Posté par
Dactyle
re : Algorithme de factorisation 02-01-14 à 22:53

Merci je vais essayer
Mais une fois que j'ai la liste des nombres premiers comment je trouve les deux facteurs premiers ? Parce que dans mon algorithme c'est pour chercher les deux facteurs à la fin qu'il y a trop de boucles, pas pour établir la liste...

Posté par
Dactyle
re : Algorithme de factorisation 02-01-14 à 22:54

Ah je lis le deuxième message j'avais pas vu

Posté par
ravinator
re : Algorithme de factorisation 02-01-14 à 23:07

En fait, il s'avère que ta méthode pour générer la liste des nombres premiers est bien plus efficace que la mienne, donc conserve-la
La où ça coinçait, c'était dans la recherche du couple solution.
Du coup, il faut quand même implémenter la test de primalité, générer ta liste de nombres premiers tel que tu l'as fait, et enfin utiliser la recherche du couple grâce à la méthode de mon dernier post

Posté par
Dactyle
re : Algorithme de factorisation 02-01-14 à 23:08

En gardant les notations de mon algorithme de départ, pour traduire "m/p[i] est premier" j'ai essayé "p(m/p[i])!=0" mais il y a "erreur dans l'exécution"... Comment faire ?

Posté par
ravinator
re : Algorithme de factorisation 02-01-14 à 23:16

Erf c'est vrai que c'est un tableau et on y a accès plus facilement que le type liste abstraite.... Du coup oui il est beaucoup plus pertinent de chercher si m/p[i] n'est pas nul dans le tableau...
Es-tu sûr qu'il ne s'agisse pas d'un problème de syntaxe ?
Normalement ça serait p[m/p[i]] avec des crochets deux fois ?

Bref désolé mais mon pauvre petit test ne servait à rien en fin de compte xD

Posté par
Dactyle
re : Algorithme de factorisation 02-01-14 à 23:27

Effectivement c'était qu'une erreur de syntaxe merci ^_^
Parfait tout marche bien maintenant, finalement 406421=547*743 !
Merci beaucoup en tout cas !

Ah si j'aurais une dernière question : y a-t-il un moyen d'arrêter la boucle "pour .. allant de .. à .." lorsque la condition est remplie, pour gagner un peu de temps ?

Posté par
ravinator
re : Algorithme de factorisation 02-01-14 à 23:33

Oui bien sûr, il suffit d'utiliser une boucle TANT QUE, qui aurait cette allure :

i Est de Type : Nombre
continuer Est de Type : Booléen

i Prend la valeur 2
Continuer Prend la valeur VRAI

TANT QUE i <= sqrt(m) ET Continuer :
si p[i] =! 0 ET m % p[i] = 0 & p[m/p[i]] != 0 alors : Continuer Prend la Valeur FAUX
sinon : i Prend la valeur i+1
FIN TANT QUE

si Continuer = FAUX alors :
AFFICHER " p[i] * p[m/p[i]] "
sinon :
AFFICHER : " pas de solution "

Posté par
mathafou Moderateur
re : Algorithme de factorisation 02-01-14 à 23:34

Bonjour,

mon avis : cet algorithme par construction préalable d'une table des nombres premiers jusqu'à M est peu efficace, en particulier il calcule des tas de nombres premiers inutiles.

sans parler de l'implémentation de la table des nombres premiers qui est "pleine de trous" donc peu efficace, en fait il ne s'agit absolument pas d'une table de nombres premiers mais d'une table d'indicateurs qui pour tous les nombres premiers ou pas mémorise s'il l'est (premier).

et les boucles de boucles pour calculer cette table de nombres premiers
(un tant que dans une boucle pour) seraient bien mieux utilisées pour décomposer directemment M en facteurs premiers, sans crible ni rien, ce qui fait au pire (M)/2 boucles en gros, boucle simples, très largement à la portée d'Algobox. (moins de 320 boucles)

le seul intérêt de créer ainsi une table de nombres premiers serait pour décomposer des listes de nombres en nombres premiers (et pas un seul nombre)
alors ces nombres premiers étant calculés une fois pour toutes, on aurait un gain effectif d'autant plus important qu'on aurait plus de nombres à décomposer.
étant bien entendu que la table de nombres premiers doit être une vraie table qui ne contient que les nombres premiers
p[0] = 2
p[1] = 3
p[2] = 5
p[3] = 7
p[4] = 11 etc

sinon quel intérêt d'être obligé de tester à la fin en fait tous les couples de nombres premiers ou pas ???
les non premiers donnent un produit nul mais ils sont testés quand même !!! inutile et pur gaspillage.

Posté par
Dactyle
re : Algorithme de factorisation 02-01-14 à 23:42

Merci ravinator

mathafou comment obtenir une liste ne contenant que les nombres premiers alors ?

Posté par
ravinator
re : Algorithme de factorisation 02-01-14 à 23:49

Bonsoir mathafou

Pour pouvoir décomposer M en produits de facteurs premiers, cela ne demande-t-il pas de connaître les-dits facteurs premiers pouvant intervenir dans la décomposition ? Du coup une liste de ceux-ci me semble nécessaire, même si la manière dont on l'a calculée ici laisse plein de trous, non?

Comment ferais-tu ?  

Posté par
mathafou Moderateur
re : Algorithme de factorisation 03-01-14 à 00:07

Bof.
et pas de liste du tout ça ne te convient pas ?

pour obtenir une liste de nombres premiers avec le crible d'Eratostène comme tu l'utilises, il faudrait en plus à la fin "compacter" la liste (ce qui est une opération lourde)
mieux faire deux listes :
- le crible
- la liste des nombres premiers dans laquelle on ne met que des nombres premiers au fur et à mesure qu'on les "découvre" dans le crible.

je reprends ton algorithme. (en langage naturel les lourdeurs d'Algobox non merci)


VARIABLES
NOMBRE m, i, j, np
LISTE crible
LISTE p

DEBUT_ALGORITHME
  LIRE m
  np = 0    // nombre de nombres premiers connus : aucun
  POUR i de 2 à m
     |   crible[i] = i  / initialisation du crible (à n'importe quoi  0)
  POUR i de 2 à sqrt(m)
     |   SI (crible[i]!=0)
     |       |  p[np] = i   // un nombre premier trouvé
     |       |  np = np+1
     |       |  j = i
     |       |  TANT_QUE (j<=m)
     |       |      |   j PREND_LA_VALEUR j+i
     |       |      |   crible[j] = 0
// ici on a dans p[0..np-1] la liste sans trous des seuls nombres premiers < m

le fin du fin : comme les nombres premiers trouvés sont < au candidats testés, les deux listes peuvent être une seule et même zone mémoire

Posté par
Dactyle
re : Algorithme de factorisation 03-01-14 à 00:29

D'accord merci beaucoup et tu dis qu'on peut le faire sans liste ?

Posté par
mathafou Moderateur
re : Algorithme de factorisation 03-01-14 à 00:39

sans table de nombres premiers du tout, et en plus ça donne même la décomposition de n'importe quel nombre pas forcément composé de deux facteurs seulement.

puisque de toute façon on balaye tous les i de 2 à m dans cet ordre, quand on en trouve un qui divise m ce sera un diviseur premier de m (puisqu'il n'y a pas de diviseur plus petit !!)

reste à trouver les autres diviseurs premiers de m
pour cela on divise m par ce diviseur premier là et on continue
ce qui donne :

Variables :
Nombres m, p, e

Algorithme :
lire m
p = 2
tant que p² < m // test plus rapide que via m
e = 0
tant que p divise m // sert en même temp de "si"
m = m/p
e = e+1
si e != 0
// on a un diviseur premier p a l'exposant e : l'afficher
afficher p et e (p^e)
p = p+1
si m != 1
// le reliquat est premier
afficher m
fini.

on peut améliorer le programme en faisant environ deux fois moins de boucles car tous les nombres premiers sauf 2 sont impairs :

Variables :
Nombres m, p, en d

Algorithme :
lire m
p = 2
d = 1
tant que p² < m // test plus rapide que via m
e = 0
tant que p divise m // sert en même temp de "si"
m = m/p
e = e+1
si e != 0
// on a un diviseur premier p a l'exposant e : l'afficher
afficher p et e (p^e)
p = p+d
d = 2 // les suivants sont de deux en deux
si m != 1
// le reliquat est premier
afficher m
fini.

résultat (exemple) :
m = 350202312

2^3
3^3
17
283
337

150 boucles effectuées en tout

Posté par
mathafou Moderateur
re : Algorithme de factorisation 03-01-14 à 00:41

PS : errata p² m bien entendu
sinon le programme serait en échec sur un nombre qui serait le carré d'un nombre premier

Posté par
ravinator
re : Algorithme de factorisation 03-01-14 à 11:58

Merci mathafou ! En effet je n'avais jamais réalisé que le premier diviseur que l'on trouverait serait premier. Du coup certes ça va beaucoup plus vite.

Posté par
Dactyle
re : Algorithme de factorisation 04-01-14 à 15:02

Ah oui j'avais pas pensé que faire la décomposition en facteurs premiers marcherait même s'il n'y a que deux facteurs ^_^ (=> go apprendre le théorème fondamental de l'arithmétique)
En plus j'en avais déjà fait un comme ça qui ressemble au tien il y a pas longtemps
Merci *_*



Vous devez être membre accéder à ce service...

Pas encore inscrit ?

1 compte par personne, multi-compte interdit !

Ou identifiez-vous :


Rester sur la page

Inscription gratuite

Fiches en rapport

parmi 1730 fiches de maths

Désolé, votre version d'Internet Explorer est plus que périmée ! Merci de le mettre à jour ou de télécharger Firefox ou Google Chrome pour utiliser le site. Votre ordinateur vous remerciera !