begin process at 2012 05 27 15:26:55
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Maths & Algorithmes

 > DÉCOMPOSITION EN FACTEURS PREMIERS AVEC GMP

DÉCOMPOSITION EN FACTEURS PREMIERS AVEC GMP


 Information sur la source

Note :
10 / 10 - par 1 personne
10,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Maths & Algorithmes Classé sous :entiers, grands nombres, décomposition, facteurs premiers, gmp Niveau :Débutant Date de création :28/11/2010 Date de mise à jour :02/12/2010 10:41:59 Vu / téléchargé :2 659 / 84

Auteur : pgl10

Ecrire un message privé
Site perso
Commentaire sur cette source (10)
Ajouter un commentaire et/ou une note

 Description

Cliquez pour voir la capture en taille normale
Voici un programme développé en Visual C++ 6.0 qui calcule la décomposition en facteurs premiers d'un nombre entier positif éventuellement de grande taille. On peut très largement dépasser la limite des int et même des __int64. La bibliothèque gmp : http://cs.nyu.edu/exact/core/gmp/ est donc utilisée pour cette raison. La documentation gmp-man-4.1.2.pdf est encore disponible. La méthode de calcul est simplement la méthode naïve. Le temps de calcul est très variable, il peut être excessivement long quand on rencontre un nombre premier de très grande taille. C'est en fait, un exemple simple pour montrer l'utilisation de gmp. Pour un test de primalité, ce n'est pas toujours un très bon exemple. On s'intéresse ici uniquement à la décomposition en facteurs premiers.

Source

  • #include <stdio.h>
  • #include <stdlib.h>
  • #include <gmp.h>
  • int main (int argc, char *argv[]) { // décomposition d'un entier n quelconque
  • mpz_t n,i,ii,q; // en produit de nombres premiers
  • unsigned int s,t[]={4,2,4,2,4,6,2,6};
  • mpz_init(n);
  • mpz_init(i);
  • mpz_init(ii);
  • mpz_init(q);
  • // lecture du nombre n à décomposer
  • if(argc==2) gmp_sscanf(argv[1],"%Zd",n);
  • else {
  • input: printf("\nEntrez un nombre entier plus grand que 1 : ");
  • gmp_scanf("%Zd",n);
  • if(mpz_cmp_si(n,2)<0) goto input; // if(n<2) goto input
  • }
  • s=2;
  • // est-ce que s divise n une ou plusieurs fois ?
  • prems : if(mpz_cmp_ui(n,s)==0) goto fin; // si n = s
  • if(mpz_divisible_ui_p(n,s)) { // si s divise n
  • mpz_div_ui(q,n,s); // q = n / s
  • gmp_printf("\n\n %Zd = %Zd * %d",n,q,s);
  • mpz_set(n,q); // n = n / s
  • goto prems;
  • }
  • if(s==2) {s=3; goto prems;}
  • if(s==3) {s=5; goto prems;}
  • s=0;
  • mpz_set_si(i,7); // i = 7
  • mpz_set_si(ii,49); // ii = 49
  • // à partir de i, calcul du plus petit diviseur i de n ( i sera premier )
  • boucle: for(;;) { // pour chaque valeur de i
  • if(mpz_cmp(ii,n)>0) goto fin; // if(i*i>n) : donc n est premier
  • if(mpz_divisible_p(n,i)!=0) { // si i divise n
  • mpz_div(q,n,i); // q = n / i
  • gmp_printf("\n\n %Zd = %Zd * %Zd",n,q,i);
  • mpz_set(n,q); // n = n / i
  • goto boucle;
  • }
  • else { // si i ne divise pas n on devrait prendre pour i le nombre
  • mpz_add_ui(i,i,t[s++]); // premier suivant, mais il n'est pas connu. Donc, on prend
  • if(s==8) s=0; // l'entier suivant en évitant les multiples de 2, 3 et 5
  • mpz_mul(ii,i,i); // ii = i * i
  • }
  • }
  • fin: gmp_printf("\n\n %Zd est premier\n\n\n",n);
  • mpz_clear(n);
  • mpz_clear(i);
  • mpz_clear(ii);
  • mpz_clear(q);
  • system("pause");
  • return 0;
  • }
#include <stdio.h>
#include <stdlib.h>
#include <gmp.h>
int main (int argc, char *argv[]) {  // décomposition d'un entier n quelconque 
    mpz_t n,i,ii,q;                  // en produit de nombres premiers
    unsigned int s,t[]={4,2,4,2,4,6,2,6};
    mpz_init(n);	
    mpz_init(i);	
    mpz_init(ii);	
    mpz_init(q);	
//   lecture du nombre n à décomposer
    if(argc==2) gmp_sscanf(argv[1],"%Zd",n);
    else {       
        input: printf("\nEntrez un nombre entier plus grand que 1 : ");
        gmp_scanf("%Zd",n);
        if(mpz_cmp_si(n,2)<0) goto input;  // if(n<2) goto input
    } 
    s=2;
//   est-ce que s divise n une ou plusieurs fois ?
    prems : if(mpz_cmp_ui(n,s)==0) goto fin;   // si n = s
    if(mpz_divisible_ui_p(n,s)) {              // si s divise n
        mpz_div_ui(q,n,s);                     // q = n / s
        gmp_printf("\n\n %Zd = %Zd * %d",n,q,s); 
        mpz_set(n,q);                          // n = n / s
        goto prems;
    }
    if(s==2) {s=3; goto prems;}
    if(s==3) {s=5; goto prems;}
    s=0;
    mpz_set_si(i,7);                   // i = 7
    mpz_set_si(ii,49);                 // ii = 49
//    à partir de i, calcul du plus petit diviseur i de n ( i sera premier )
    boucle: for(;;) {                  // pour chaque valeur de i 
        if(mpz_cmp(ii,n)>0) goto fin;  // if(i*i>n) : donc n est premier 
        if(mpz_divisible_p(n,i)!=0) {  // si i divise n 
            mpz_div(q,n,i);            // q = n / i
            gmp_printf("\n\n %Zd = %Zd * %Zd",n,q,i);
            mpz_set(n,q);              // n = n / i
            goto boucle;
        }
        else {                       // si i ne divise pas n on devrait prendre pour i le nombre
            mpz_add_ui(i,i,t[s++]);  // premier suivant, mais il n'est pas connu. Donc, on prend
            if(s==8) s=0;            // l'entier suivant en évitant les multiples de 2, 3 et 5
            mpz_mul(ii,i,i);         // ii = i * i
        }
    }
    fin: gmp_printf("\n\n %Zd est premier\n\n\n",n); 
    mpz_clear(n);	
    mpz_clear(i);	
    mpz_clear(ii);	
    mpz_clear(q);	
    system("pause");
    return 0;
} 

 Conclusion

On peut l'utiliser en cliquant sur diviseurs.exe ou avec un raccourci ou encore avec un fichier *.bat. Toutes remarques ou améliorations sont les bienvenues. Merci, pgl10

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Historique

28 novembre 2010 15:49:23 :
Clarification
29 novembre 2010 13:38:18 :
Présentation améliorée
30 novembre 2010 11:36:22 :
Pour aller un peu plus vite
02 décembre 2010 10:42:00 :
Encore un peu plus simple et un peu plus rapide

 Sources du même auteur

Source avec Zip Source avec une capture UNE LISTE HÉTÉROGÈNE DOUBLEMENT CHAINÉE
Source avec Zip Source avec une capture POUR AFFICHER LES CARACTÈRES ACCENTUÉS SOUS WINDOWS EN MODE ...
Source avec Zip Source avec une capture CONVHTML : UN UTILITAIRE DE CONVERSION POUR FICHIERS HTML
Source avec Zip Source avec une capture AFFIMOFF : UNE VISIONNEUSE 3D AVEC PARAMÉTRISATION ET TEXTUR...
Source avec Zip Source avec une capture CRIBLE D'ERATOSTHÈNE OPTIMISÉ

 Sources de la même categorie

Source avec Zip UN EXAMPLE D'APPLICATION EN CUDA DE L'ALGORITHME DE SCAN POU... par oguzaras
Source avec Zip Source avec une capture CHIFFREMENT DE VIGENERE par lajouad
Source avec Zip Source avec une capture ANALYSE SYNTAXIQUE par lajouad
Source avec Zip Source avec une capture STRUCTURE D'UNE MATRICE PAR LES LISTE LINÉAIRE (NON CONTUGUS... par benzarabel
Source avec Zip Source avec une capture DESSINER UNE ARBRE BINAIRE( MODE CONSOLE): par benzarabel

 Sources en rapport avec celle ci

PROJET DE CRYPTOGRAPHIE: RSA À JEU REDUIT D'INSTRUCTION par samatarahmed
Source avec Zip Source avec une capture UN INTERPRÉTEUR POUR RATIONNELS DE GRANDES TAILLES par pgl10
Source avec Zip Source avec une capture CRYPTOSYSTÈME ELGAMAL LIBRAIRIE GMP par louelh95
Source avec Zip Source avec une capture OP4 UN INTERPRÉTEUR POUR ENTIERS DE TRÈS GRANDE TAILLE par pgl10
Source avec une capture POWER MATH: TESTE DE VITESSE ENTIERS VS REELS , CLASS VS STR... par dedalusman

Commentaires et avis

Commentaire de pop70 le 28/11/2010 15:45:12 10/10

Ouhou ! Ce code est posté pile au bon moment !
Je viens de déposer une question sur le forum pour savoir comment manipuler de très grands nombres, et je trouve la réponse 2mn plus tard (GMP) :)
D'ailleurs si je cherchais de à faire de très grands nombres, c'est pour essayer de faire un petit programme de cryptage RSA expliqué sur un site.
Pour valeur d'exemple il donne un produit de 2 nombres premiers égal à 283189. Puis ils disent que dans la pratique, il faut des nombres bien plus grands, car celui-ci peut-être rapidement décomposé... Il font bien de le dire, j'ai testé ton programme est en moins d'1/10 de seconde il l'a décomposé en 503x563.

Vraiment bravo! Je pense que ce code va m'être bien utile et à beaucoup d'autre aussi.
De plus, il est très bien commenté, et ça facilite grandement la lecture, surtout lorsqu'on ne connait pas encore, comme moi, la librairie GMP.

Encore une fois Merci pgl10 !

Commentaire de Bacterius le 28/11/2010 22:50:13

@Pop70 : Pour info voici un exemple de nombre utilisé en cryptographie, par RSA (et encore, c'est un petit) :

13506641086599522334960321627880 596993888147560566702752448 514385152651060485953383394028715 0571909441798207282164471 5513736804197039641917430 46496589274256239341020864383202110 37295872576235850964311056407350150818 75106765946292055636855294752135 008528794163773285339061097505 44334999811150056977236890927563

Ce que je suggère à Pgl10 est d'essayer d'implémenter à présent le test de primalité de Miller-Rabin avec gmp (assez simple), et ensuite pour un vrai challengé tenter d'implémenter le crible quadratique : http://fr.wikipedia.org/wiki/Crible_quadratique. C'est juste une suggestion évidemment mais ça donne un bon défi très satisfaisant quand on l'atteint.

Cordialement, Bacterius !

Commentaire de pgl10 le 28/11/2010 23:26:37

=> POP70 : merci pour cet aimable commentaire.
=> BACTERIUS : le test de primalité de Miller-Rabin avec gmp est disponible à http://en.literateprograms.org/Miller-Rabin_primality_test_(C,_GMP). Je l'ai compilé. Chez moi, le grand nombre écrit ci-dessus est détecté composite. Je suppose qu'on peut aussi le trouver ailleurs et notamment sur cppfrance avec NTL. Par contre je signale que la publication de ce grand nombre casse la mise en page habituelle de la page Internet Explorer actuelle. J'avais déjà indiqué que mon petit logiciel diviseurs.exe n'était pas fait pour faire un bon test de primalité, comme ceux de Miller-Rabin, de AKS ou d'autres, mais seulement d'exercice pour utiliser gmp. Ceci dit merci pour les remarques pour lesquelles je suis d'accord. Bye, pgl10

Commentaire de Bacterius le 28/11/2010 23:30:14

Oui ça la casse aussi chez moi, je ne m'attendais pas à ça. Si un admin pouvait mettre quelques retours chariots dans mon commentaire pour rétablir la mise en page, ce serait gentil.
Encore une fois je ne critiquais pas ton code mais je te proposais des idées dans la continuité de ce source, c'est tout :p

Cordialement, Bacterius !

Commentaire de pgl10 le 29/11/2010 13:39:44

Merci à Nicolas SOREL (Nix) pour avoir coupé en morceaux le très grand nombre ci-dessus et avoir rétabli la présentation habituelle.
A noter que les tests de primalité exacts ou probabilistes sont bien sûr voisins du sujet traité ici mais en général ils ne font pas la décomposition en facteurs premiers. Ces deux problèmes sont sont complémentaires mais différents.

Commentaire de pgl10 le 29/11/2010 17:41:27

Pour ceux qui voudraient approfondir, il est probablement utile de préciser que GMP possède des fonctions spécialisées et des programmes optimisés de démonstrations pour divers problèmes parmi lesquels : factorize, pour factoriser un grand entier, isprime, pour la primalité d'un grand entier et primes, pour afficher les nombres premiers compris entre deux grands entiers.

Commentaire de smaida le 06/12/2010 21:58:50

    * #include <stdio.h>
    * #include <stdlib.h>
    * #include <gmp.h>
    * int main (int argc, char *argv[]) { // décomposition d'un entier n quelconque
    * mpz_t n,i,ii,q; // en produit de nombres premiers
    * unsigned int s,t[]={4,2,4,2,4,6,2,6};
    * mpz_init(n);
    * mpz_init(i);
    * mpz_init(ii);
    * mpz_init(q);
    * // lecture du nombre n à décomposer
    * if(argc==2) gmp_sscanf(argv[1],"%Zd",n);
    * else {
    * input: printf("\nEntrez un nombre entier plus grand que 1 : ");
    * gmp_scanf("%Zd",n);
    * if(mpz_cmp_si(n,2)<0) goto input; // if(n<2) goto input
    * }
    * s=2;
    * // est-ce que s divise n une ou plusieurs fois ?
    * prems : if(mpz_cmp_ui(n,s)==0) goto fin; // si n = s
    * if(mpz_divisible_ui_p(n,s)) { // si s divise n
    * mpz_div_ui(q,n,s); // q = n / s
    * gmp_printf("\n\n %Zd = %Zd * %d",n,q,s);
    * mpz_set(n,q); // n = n / s
    * goto prems;
    * }
    * if(s==2) {s=3; goto prems;}
    * if(s==3) {s=5; goto prems;}
    * s=0;
    * mpz_set_si(i,7); // i = 7
    * mpz_set_si(ii,49); // ii = 49
    * // à partir de i, calcul du plus petit diviseur i de n ( i sera premier )
    * boucle: for(;;) { // pour chaque valeur de i
    * if(mpz_cmp(ii,n)>0) goto fin; // if(i*i>n) : donc n est premier
    * if(mpz_divisible_p(n,i)!=0) { // si i divise n
    * mpz_div(q,n,i); // q = n / i
    * gmp_printf("\n\n %Zd = %Zd * %Zd",n,q,i);
    * mpz_set(n,q); // n = n / i
    * goto boucle;
    * }
    * else { // si i ne divise pas n on devrait prendre pour i le nombre
    * mpz_add_ui(i,i,t[s++]); // premier suivant, mais il n'est pas connu. Donc, on prend
    * if(s==8) s=0; // l'entier suivant en évitant les multiples de 2, 3 et 5
    * mpz_mul(ii,i,i); // ii = i * i
    * }
    * }
    * fin: gmp_printf("\n\n %Zd est premier\n\n\n",n);
    * mpz_clear(n);
    * mpz_clear(i);
    * mpz_clear(ii);
    * mpz_clear(q);
    * system("pause");
    * return 0;
    * }

Commentaire de ccgousset le 17/12/2011 23:18:00

Jai vu ton dernier source sur les carac accentués c'est malin. Ma question utilise tu gmp avec vc6++ et en mode cpp (avecx gmpxx.h et les librairies ...xx.lib ou ...xx.dll si oui connais tu l'astuce pour faire marcher gmpxx.h et vc++. Voila a plus et Merci le Gpl.

Commentaire de pgl10 le 18/12/2011 20:19:33

Ccgousset : Je ne connais pas bien les gmpxx.h et gmpxx.lib. J'utilise avec Visual C++ 6.0 la version 4.1.2 de GMP citée dans la description. Cette version vient avec gmp.h et gmp.lib qui n'ont aucun problème de compilation ou de link edit. C'est une version plus ancienne, mais on trouve assez facilement sur Internet des documentations pour cette version. Et mon C++ est en fait principalement du C, les parties spécifiques du C++ ne sont guère utilisées ici. Désolé de ne dire rien de mieux.

Commentaire de ccgousset le 19/12/2011 12:46:26

Merci Pgl10 je cherche mais ai beaucoup de mal a trouver (gmpxx.h et vc) chou blanc en fait. A plus Merci.

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Aruthmétique sur grands entiers ??? [ par Cygnus ] J'ai à effectuer des opérations (+,-,'/,*) sur des grands nombres entiers (positifs et négatifs), tout en utilisant les fonctions membre de la classe Division de deux tableaux d'entiers [ par BenHur ] Bonjour, j'ai deux tableaux d'entiers dont chaque indice contient un nombre de 0 à 9. Je dois faire des opérations mathématiques sur chacun de ces ind manipulaton de trés grands entiers [ par Orkblutt ] Salut,j'aimerai implementer une classe qui me permettrai de manipuler (+,-, /,*,%) des grands nombres (Nb&gt;32bits) mais je ne sais pas du tout comme Urgent...classe de manipulation de grands entiers [ par Orkblutt ] Salut,j'aimerai implementer une classe qui me permettrai de manipuler (+,-, /,*,%) des grands nombres (Nb&gt;32bits) mais je ne sais pas du tout comme Somme d'entiers [ par PiraTmaT ] Bonjour,Je dispose d'une suite d'un certain nombre d'entiers aléatoires inférieurs ou égaux à 100.Je dois déterminer s'il est possible de regrouper un blindage de saisie [ par shomon ] Bonjourje souhaterai effectuer un blindage de saisie sur des entiers uniquement. Par exemple dans le code ci dessous :aff(" \nrentrez un numero entre Buffer avec WriteFile ??????????? [ par nanalye ] Bonjour tout le monde !J'ai regardé sur le forum ce qui était mis sur ce sujet mais je n'ai pas tout compris.Je dois envoyer des entiers par le biais Help me: grand nombres entiers [ par waza ] voila je suis en train de réaliser un programme de cryptage rsa mais le pb c ke je suis limiter a des entiers de 64 bits!! (avec __int64) et je me dem recherche [ par dvpm ] je suis débutant et j'essaie de mettre au point un programme qui permet à son utilistareur de rentrer des nombres (des entiers positifs) ua clavier Multiplication sur des tableaux entiers [ par kikouk ] Salut.J'ai besoin de créer une procédure sous Visual C++ qui réalise la multiplication de 2 grands entiers (stockés dans 2 tableaux (1 dimension)) et


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

Photothèque

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,874 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales