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 :

problème: stocker un grand nombre


Sujet :

C

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 18
    Par défaut [Résolu] problème: stocker un grand nombre
    salut, pour m'entrainer je voudrais faire un programme pour décomposer un nombre en facteurs premier (ce qui est déjà fait) mais j'ai un problème avec la variable "long" j'ai remarqué qu'on arrivait à sa limite à environ 1 200 000 000, après ça me marque n'importe quoi dans mon programme. Et je ne peux pas utiliser float car j'ai lu que ce type n'était pas précis du tout. Que faire ?

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 495
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 495
    Par défaut
    Citation Envoyé par G0rk4 Voir le message
    Que faire ?
    La première chose à faire est estimer la précision maximale dont tu as besoin. Dans ton cas précis, tu utilises a priori des entiers. Donc, il n'y a pas de précision après la virgule mais il y aura des limites maximum et minimum qu'il faut établir.

    Après cela, tu choisis une solution en conséquence. Soit c'est vraiment très grand mais sans être démesuré et dans ce cas-là, ça peut tenir dans un long long, soit c'est arbitrairement grand et dans ce cas, il faut utiliser les ressources de ton ordinateur pour y stocker les éléments de ton nombre et les manipuler toi-même comme tu le ferais sur une feuille de papier.

    À ce stade, tu peux soit écrire tes propres routines, ce qui peut s'avérer très efficace selon le contexte en restant raisonnablement compliqué, soit utiliser GMP.

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

    limite à environ 1 200 000 000
    Hypothèse : le processeur utilisé est un 32bits.

    Déjà, si on travaille sur des nombres entier, on peut utiliser unsigned long au lieu de long. On passe de -2147483647 --> 2147483647 à 0 --> 4294967295.
    Si on veut plus de précision, on peut passer à des types de 64 bits : unsigned long long, la limite supérieure devient alors 18446744073709551615.

    -->FAQ

    Si cela ne suffit toujours pas, il faut alors s'orienter vers des lib spécialisées comme gmp.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 18
    Par défaut
    ok merci j'ai essayé avec un long long mais je suis quand même limité regardez je vous ai fait un screen
    il me fait des trucs bizarres avec des nombres trop grands... sinon ça marche très bien en dessous de 10^10
    Images attachées Images attachées  

  5. #5
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 970
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 970
    Par défaut
    Jai,

    Problème récurrent.

    As-tu compris que les valeurs sont limitées par la taille du type utilisé ?

  6. #6
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 495
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 495
    Par défaut
    Citation Envoyé par G0rk4 Voir le message
    ok merci j'ai essayé avec un long long mais je suis quand même limité regardez je vous ai fait un screen
    il me fait des trucs bizarres avec des nombres trop grands... sinon ça marche très bien en dessous de 10^10
    1) As-tu réellement besoin de nombres si grands ?

    2) Ces nombres ne tiennent pas dans un long 32 bits, mais dans un long long 64 bits, si. C'est donc ta façon de les saisir et de les restituer qui n'est pas correcte.

    Montre-nous ton code, qu'on voit ce qui cloche. Essaie d'utiliser strtoll() (avec deux L) pour lire ton nombre et %lld si tu utilises printf().

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 18
    Par défaut
    voila là où je déclare le nombre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        long long nombre = 0;
     
    printf("entrez un nombre a decomposer\n");
    scanf("%ld", &nombre);
     
    algo(nombre);
    et voila ma fonction de décomposition

    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
    void algo(long long nombre)
    {
         char phrase[5000], phrase2[100];
    long i = 2, j = 0;
    sprintf(phrase, "%ld est divisible par : ", nombre);
    for(i = 2 ; i < sqrt(nombre) + 1 ; i++)
    {
          while((nombre / i) * i == nombre)
          {
                             j++;
                             nombre = nombre / i;
                             }
                             if(j != 0)
                             {
                                  sprintf(phrase2, "%ld^%ld x ", i, j);
                                  strcat(phrase, phrase2);
                                  j = 0;
                                  }
          }
          if(nombre != 1)
          {
                     sprintf(phrase2, "%ld ", nombre);
                     strcat(phrase, phrase2);   
                     }
    else
    {
                     strcat(phrase, "1");   
                     }  
                printf("%s\n", phrase);     
    }
    je me demande si le problème ne viendrait pas du "char" là où je stocke ma phrase, vu que le char n'est que du 8bit et donc très limité ?

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 18
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    1) As-tu réellement besoin de nombres si grands ?

    2) Ces nombres ne tiennent pas dans un long 32 bits, mais dans un long long 64 bits, si. C'est donc ta façon de les saisir et de les restituer qui n'est pas correcte.

    Montre-nous ton code, qu'on voit ce qui cloche. Essaie d'utiliser strtoll() (avec deux L) pour lire ton nombre et %lld si tu utilises printf().
    je n'ai pas vraiment besoin de nombres si grands, c'est juste pour m'entrainer, mais quand quelquechose ne va pas j'aime comprendre pourquoi pour progresser

  9. #9
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 495
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 495
    Par défaut
    Citation Envoyé par G0rk4 Voir le message
    je n'ai pas vraiment besoin de nombres si grands, c'est juste pour m'entrainer, mais quand quelquechose ne va pas j'aime comprendre pourquoi pour progresser
    C'est une bonne chose.

    Citation Envoyé par G0rk4 Voir le message
    je me demande si le problème ne viendrait pas du "char" là où je stocke ma phrase, vu que le char n'est que du 8bit et donc très limité ?
    Avant ça, il reste plusieurs choses à faire :

    1) Mets tous tes nombres au format long long (tes autres variables sont restées en long). Il y a des transtypages faits automatiquement, mais ils sont implicites et peu visibles.

    2) sqrt() attend un double ! Là encore, le cast est automatique mais un double ne peut contenir un long long en totalité. Tu peux à la limite convertir çà encore en long double et utiliser sqrtl() à la place, mais ça commence à faire beaucoup ! Et ça ne règle pas le problème de fond.

    3) Utilise %lld pour afficher des long long avec printf() et %Lf pour les long double. Mais bon, c'est pas courant, les long double.

    4) Souviens-toi que printf() est une fonction ordinaire qui attend un nombre variable d'arguments indéfinis. C'est pour ça qu'on commence par une chaîne qui en donne le format. Ça veut que contrairement aux autres fonctions, Le compilateur ne transtypera les arguments passés. Donc si tu utilises « %f » et que tu passes un entier, la valeur affichée sera forcément incorrecte, même si le calcul est juste.

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 18
    Par défaut
    j'ai changé tous les types en long long, et mit des %lld mais ça ne change rien du tout, le problème viendrait donc de sqrt() ? il faudrait que je réécrive tout le prog sans sqrt ?

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 18
    Par défaut
    en fait il ne prend simplement pas mon long long il ne prend même pas mon unsigned long
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int main(int argc, char *argv[])
    {
    while(1)
    {
        unsigned long test = 0;
        scanf("%ld", &test);
        printf("%ld\n", test);
    }
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    il ne prend pas de nombre au dessus de 2147483647 (limite du long)
    c'est donc un problème de version ou quelque chose comme ça ?

  12. #12
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 495
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 495
    Par défaut
    Citation Envoyé par G0rk4 Voir le message
    il ne prend pas de nombre au dessus de 2147483647 (limite du long) c'est donc un problème de version ou quelque chose comme ça ?
    Il faut que tu lises la doc' de ces fonctions, et que tu la comprennes bien si tu as l'intention des les utiliser sérieusement : d correspondent à des nombres entiers signés. S'ils ne le sont pas, il faut utiliser u à la place, et comme les fonctions scanf() et printf() ne peuvent pas connaître le type de ce que tu passes, elles ne peuvent pas prendre la décision à ta place.

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 18
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Il faut que tu lises la doc' de ces fonctions, et que tu la comprennes bien si tu as l'intention des les utiliser sérieusement : d correspondent à des nombres entiers signés. S'ils ne le sont pas, il faut utiliser u à la place, et comme les fonctions scanf() et printf() ne peuvent pas connaître le type de ce que tu passes, elles ne peuvent pas prendre la décision à ta place.
    ok ouais je viens de lire ça en fait désolé, quand je mets %u ça marche je peux mettre jusqu'à 4 200 000 000 et des poussières, mais pourquoi cela ne marche pas avec long long et %lld comme tu me l'as indiqué ??

  14. #14
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 495
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 495
    Par défaut
    Citation Envoyé par G0rk4 Voir le message
    ok ouais je viens de lire ça en fait désolé, quand je mets %u ça marche je peux mettre jusqu'à 4 200 000 000 et des poussières, mais pourquoi cela ne marche pas avec long long et %lld comme tu me l'as indiqué ??
    As-tu essayé %llu ?

  15. #15
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 18
    Par défaut
    oui j'ai même essayé de mettre "LL" après avoir déclaré la variable comme c'est marqué sur des tutos, rien n'y fait.

  16. #16
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 515
    Par défaut
    Dans scanf, %ld lit un long. Pour lire un long long c'est %Ld. Pour lire un unsigned long long c'est %Lu.

    Dans printf, c'est %lld pour long long et %llu pour unsigned long long.

  17. #17
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 495
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 495
    Par défaut
    Citation Envoyé par G0rk4 Voir le message
    oui j'ai même essayé de mettre "LL" après avoir déclaré la variable comme c'est marqué sur des tutos, rien n'y fait.
    chezmoicamarche.com

    ll-, c'est un préfixe pour les long long (entiers, donc), L- est un préfixe pour les long double, ce qui est différent. LL, je ne connais pas.

  18. #18
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 18
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    chezmoicamarche.com

    ll-, c'est un préfixe pour les long long (entiers, donc), L- est un préfixe pour les long double, ce qui est différent. LL, je ne connais pas.
    Ok... j'avais vu ça dans un tuto sur un autre site
    si même les tutos sont faux... :s

  19. #19
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 515
    Par défaut
    Le tuto n'est pas faux, mais il ne parle par de la même chose.
    Bon tu m'a l'air d'avoir du mal, alors :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int
    main(int argc, char *argv[])
    {
            while (1) {
                    unsigned long long test = 0;
                    scanf("%Lu", &test);
                    printf("%llu\n", test);
            }
            return EXIT_SUCCESS;
    }
    Voilà. En plus il faut tester le retour du scanf.

  20. #20
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 18
    Par défaut
    ça ne marche toujorus pas chez moi même avec ton code :s
    limité à 4 200 000 000 et des poussières, comme un unsigned long en fait...
    j'utilise Dev C++ 4.9.9.2

Discussions similaires

  1. problème avec des grands nombres
    Par lebelge dans le forum Code::Blocks
    Réponses: 1
    Dernier message: 29/07/2011, 06h51
  2. problème avec des grands nombres
    Par lebelge dans le forum Débuter
    Réponses: 8
    Dernier message: 28/07/2011, 21h00
  3. Stocker des grands nombres
    Par TrexXx dans le forum Débuter
    Réponses: 28
    Dernier message: 31/12/2008, 02h34
  4. Réponses: 4
    Dernier message: 28/03/2008, 19h18
  5. Type PostgreSQL pour stocker des grands nombres
    Par K-Kaï dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 08/06/2006, 20h26

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