IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Conception d'une librairie de calculs sur les grands nombres


Sujet :

C

  1. #1
    Membre à l'essai
    Inscrit en
    Septembre 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 22
    Points : 15
    Points
    15
    Par défaut Conception d'une librairie de calculs sur les grands nombres
    Bonjour!
    Je cherche actuellement à créer une librairie de calcul sur les grands nombres. L'idée est la suivante:
    J'ai un grand nombre de type unsigned long int, possedant par exemple 50 chiffres.
    Je le decoupe dans un tableau, avec, par exemple encore une fois, 4 chiffres par case (les 4 premiers, puis les 4 suivants, etc...).
    Ensuite il me reste à faire mes opérations "comme à l'ecole" en considerant les blocs de chiffres! J'aimerai en premier lieu ecrire de cette manière la multiplication et le modulo.

    Mes questions sont alors:
    comment decouper mon nombre en blocs de 4 chiffres? Sans utiliser d'operateurs mathematiques sur celui ci car ils ne fonctionnent pas pour de grands nombres!!
    Puis comment gerer les fifferentes opérations entre les blocs de 4 chiffres?
    Merci d'avance si vous avez une idée!

  2. #2
    Invité(e)
    Invité(e)
    Par défaut
    Bonjour,

    Une idée serait de ne jamais travailler sur des types de base, mais seulement sur des chaines de caractères.

    En gros cela reviendrait à créer un programme qui compte comme nous : directement en décimal, sans passer par du binaire.

  3. #3
    Membre à l'essai
    Inscrit en
    Septembre 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 22
    Points : 15
    Points
    15
    Par défaut
    Oui je pensai effectivement à ca aussi. Finalement en entrée j'ai une chaine de caractere (cela me permet d'avoir des nombres tres grands).
    Ensuite je coupe cette chaine en un tableau de unsigned int où chaque case contient 4 chiffres. Il me reste donc à effectuer les calculs entre ces cases de unsigned int, a priori je n'aurai jamais de depassement. Mon problème maintenant c'est d'effectuer les opérations entre les dîtes cases. Je ne suis pas resté en char parce que je suis incapable de comprendre comment faire des calculs entre operande de type 'char'.

  4. #4
    Invité(e)
    Invité(e)
    Par défaut
    Citation Envoyé par nocta Voir le message
    Je ne suis pas resté en char parce que je suis incapable de comprendre comment faire des calculs entre operande de type 'char'.

    Dans le code ascii, les caractères codant les chiffres se suivent, il suffit donc de connaitre la valeur de '0' pour déterminer les autres valeur. Or ton compilateur connait la valeur du caractère codant 0, c'est '0'.

    Donc, pour transformer un caractère en entier, on peut faire comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    /* la caractère à convertir*/
    char c = '5';
    /* le résultat de la conversion */
    int i = c - '0';
    (Tu peux prendre ta table ascii pour vérifier.)

    Un exemple plus poussé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    #include <stdio.h>
     
    int main(void) 
    {
        int i;
        /* taille de travail*/
        const int len = 5;
        /* opérandes et résultat : chaines de caractères */
        char op_1[len+1] = "15991";
        char op_2[len+1] = "35219";
        char resultat[len+1] = "00000";
        /* retenue : ne prendra que 1 ou 0 comme valeur */
        int retenue = 0;
     
        for(i = len - 1; i >= 0; --i) {
            /* récupération des chiffres et transformation en entiers */
            int int_1 = op_1[i] - '0';
            int int_2 = op_2[i] - '0';
     
            /* addition */
            int res = int_1 + int_2 + retenue;
     
            /* retenue */
            if(res > 9) {
                if(i == 0) {
                    printf("dépassement!\n");
                } else {
                    retenue = 1;
                }
            } else {
                retenue = 0;
            }
            /* conversion du résultat en caractère */
            resultat[i] = res%10 + '0';
        }
     
        /* affichage du résultat */
        printf("  %s\n", op_1);
        printf("+\n");
        printf("  %s\n", op_2);
        printf("  -----\n");
        printf("  %s\n", resultat);
     
        return 0;
    }
    Dernière modification par Invité(e) ; 30/09/2010 à 10h23. Motif: correction bugs

  5. #5
    Membre à l'essai
    Inscrit en
    Septembre 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 22
    Points : 15
    Points
    15
    Par défaut
    ok merci, ça m'eclaire beaucoup!
    Pour l'addition c'est parfait.
    Par contre, si je comprend bien le système, ça m'oblige à considerer les caracteres un par un? Pour la multiplication, je pensai proceder par blocs de 4 chiffres pour gagner de la vitesse, mais ta solution ne marche plus en ce cas.

    Est ce que je gagne réellement de la vitesse en prenant des blocs de 4 chiffres? Car autrement t'as solution est impecc.

  6. #6
    Invité(e)
    Invité(e)
    Par défaut
    Citation Envoyé par nocta Voir le message
    Par contre, si je comprend bien le système, ça m'oblige à considerer les caracteres un par un? Pour la multiplication, je pensai proceder par blocs de 4 chiffres pour gagner de la vitesse, mais ta solution ne marche plus en ce cas.
    Est ce que je gagne réellement de la vitesse en prenant des blocs de 4 chiffres? :
    Utiliser 4 chiffres peut être une bonne méthode, mais il faut mieux commencer par quelque chose de simple et lent qui fonctionne plutôt quelque chose complexe et rapide qui ne fonctionne pas.

    Dans un premier temps, je te conseillerai donc de rester sur du chiffre à chiffre et d'optimiser quand tu en verras les limites.

  7. #7
    Membre à l'essai
    Inscrit en
    Septembre 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 22
    Points : 15
    Points
    15
    Par défaut
    Ok, je pense que tu as raison. De toute façon ca y est j'ai commencé avec du chiffre par chiffre.
    Merci beaucoup.

  8. #8
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 986
    Points
    30 986
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par nocta Voir le message
    Ok, je pense que tu as raison. De toute façon ca y est j'ai commencé avec du chiffre par chiffre.
    Merci beaucoup.
    Petite astuce: pense à inverser tes nombres. Ca te permettra de les caler sur la bonne unité.

    Exemple: tu dois additionner 123 et 45.
    Soit tu laisses dans ce sens et tu seras obligé d'additionner l'élément [3] du premier avec l'élément [2] du second, puis l'élément [2] du premier avec l'élément [1] du second etc...
    Soit tu les inverses ce qui donne 321 + 54 et là, tu additionnes les deux éléments [0] puis les deux éléments [1] puis l'élément [2] du premier qui est tout seul (mais qui pourrait avoir une retenue) ce qui donne 861 puis ensuite tu inverses le résultat => 168

    PS: ce que tu cherches à faire existe quand-même déjà => http://gcc.gnu.org/onlinedocs/gcc/Decimal-Float.html
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 942
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 942
    Points : 5 654
    Points
    5 654
    Par défaut
    Gai,
    Citation Envoyé par mabu Voir le message
    Bonjour,

    Une idée serait de ne jamais travailler sur des types de base, mais seulement sur des chaines de caractères.

    En gros cela reviendrait à créer un programme qui compte comme nous : directement en décimal, sans passer par du binaire.
    Oui, mais c'est aussi un moyen d'obtenir des performances catastrophiques.

    Les algorithmes requis s'implémentent aussi facilement en utilisant la largeur native du processeur, alors pourquoi se passer de la puissance (quand on commence à avoir besoin de ce type de calcul, on a généralement besoin d'aller vite).

    Pour nocta : faire une telle bibliothèque est assez simple, mais ça devient long à faire si tu veux optimiser correctement, et tu n'échapperas pas à l'assembleur.
    Si c'est seulement pour l'utilisation, il faut mieux prendre ce qui existe déjà, et GMP est là pour ça.
    Si les cons volaient, il ferait nuit à midi.

  10. #10
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 374
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 374
    Points : 23 631
    Points
    23 631
    Par défaut
    Citation Envoyé par droggo Voir le message
    Oui, mais c'est aussi un moyen d'obtenir des performances catastrophiques.

    Les algorithmes requis s'implémentent aussi facilement en utilisant la largeur native du processeur, alors pourquoi se passer de la puissance (quand on commence à avoir besoin de ce type de calcul, on a généralement besoin d'aller vite).
    Je plussoie.

    Ramener le problème au décimal est autant un piège à éviter qu'utiliser les formats natifs de sa machine une habitude à prendre. Mais je pense qu'à ce stade, l'important est surtout de savoir ce que nocta veut vraiment faire :

    • Écrire une lib pour pouvoir gérer les grands nombres dans ses projets. Dans ce cas, il faut plutôt se tourner vers GMP ou équivalent ;
    • Écrire cette lib pour l'exercice. Dans ce cas, se rapprocher des types natifs ;
    • Écrire cet outil à titre pédagogique, pour pouvoir afficher directement les chiffres, faire des exemples d'arithmétiques, etc. Dans ce cas, on peut travailler au niveau du chiffre décimal en le stockant dans un tableau, quitte à perdre des bits. Après tout, c'est pour des besoins similaires qu'on a défini le BCD. Mais il faut être sûr que c'est bien la finalité de la chose.

  11. #11
    Membre à l'essai
    Inscrit en
    Septembre 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 22
    Points : 15
    Points
    15
    Par défaut
    Veuillez m'excuser pour cette réponse tardive.
    En fait je souhaite concevoir cette lib pour deux choses:
    -l'utiliser dans le cadre d'un projet de cryptographie/authentification basé sur l'utilisation des courbes elliptiques,
    -et d'autre part montrer, de facon explicite, la necessité d'utiliser des algorithme spéciaux pour l'utilisation des grands nombres.

    Je suis donc à cheval entre l'utilisation d'une bonne lib telle GMP, et la conception d'une lib par mes soins. Mais plus j'avance plus je me dit que cette derniere option n'est pas vraiment réalisable, ou ne sera pas operationelle.

  12. #12
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 942
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 942
    Points : 5 654
    Points
    5 654
    Par défaut
    Goa,
    Citation Envoyé par nocta Voir le message
    -et d'autre part montrer, de facon explicite, la necessité d'utiliser des algorithme spéciaux pour l'utilisation des grands nombres.
    Il est de fait que les algorithmes "naïfs" sont vite dépassés dès que les nombres s'allongent.

    Citation Envoyé par nocta Voir le message
    Je suis donc à cheval entre l'utilisation d'une bonne lib telle GMP, et la conception d'une lib par mes soins. Mais plus j'avance plus je me dit que cette derniere option n'est pas vraiment réalisable, ou ne sera pas operationelle.
    Oui. Comme déjà dit, ce n'est pas compliqué, mais assez long à implémenter, surtout si tu veux tous les algorithmes "rapides" sur les grand nombres, sans parler du temps passé en tests ...

    À mon avis, la solution pour toi est d'utiliser une bibliothèque prête à l'emploi.
    Si les cons volaient, il ferait nuit à midi.

  13. #13
    Membre à l'essai
    Inscrit en
    Septembre 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 22
    Points : 15
    Points
    15
    Par défaut
    En ce cas une derniere question: en essayant de compiler GMP, j'obtiens une erreur à la commande 'make', et la reponse:
    make: *** Pas de cibles spécifiées et aucun makefile n'a été trouvé. Arrêt.

    Quelqu'un a une idée??

  14. #14
    Invité(e)
    Invité(e)
    Par défaut
    As tu lancé ./configure avant ?

  15. #15
    Membre à l'essai
    Inscrit en
    Septembre 2010
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 22
    Points : 15
    Points
    15
    Par défaut
    oui, j'ai suivi la procedure suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    wget http://ftp.sunet.se/pub/gnu/gmp/gmp-4.2.3.tar.gz
    tar xfz gmp-4.2.3.tar.gz
    cd gmp-4.2.3
    ./configure --enable-cxx
    make
    make check
    sudo make install
    cd ..
    rm -rf gmp-4.2.3 gmp-4.2.3.tar.gz
    cd /usr/lib/
    sudo ln -s /usr/local/lib/libgmpxx.so.4 libgmpxx.so.4

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [WD19] calculs sur les enregistrements d'une rupture dans un état
    Par elscorpio dans le forum WinDev
    Réponses: 3
    Dernier message: 14/11/2014, 14h19
  2. Calcul sur les champs d'une table
    Par cvfe13 dans le forum Requêtes et SQL.
    Réponses: 6
    Dernier message: 20/03/2012, 15h59
  3. [XL-2007] Opérations sur les grands nombres dans Q
    Par KenDev dans le forum Contribuez
    Réponses: 4
    Dernier message: 22/03/2011, 04h05
  4. Optimisation des opérations sur les grands nombres, algorithme de Knuth
    Par Jackyzgood dans le forum Algorithmes et structures de données
    Réponses: 8
    Dernier message: 21/10/2010, 20h27
  5. [C#] Calcul sur les dates avec des DateTimePicker
    Par alizee971 dans le forum Windows Forms
    Réponses: 10
    Dernier message: 02/04/2005, 17h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo