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èmes avec de (petits) grands nombres


Sujet :

C++

  1. #1
    Membre du Club
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2011
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Août 2011
    Messages : 88
    Points : 65
    Points
    65
    Par défaut Problèmes avec de (petits) grands nombres
    Bonjour,

    Je sais que ce problème a déjà été abordé plusieurs fois ici, mais je n'arrive néanmoins pas à trouver de solution ...

    J'ai un programme qui utilise le temps, mais en millisecondes. J'essaie de lui faire stocker 1 an (soit 31.536.000.000 ms) mais impossible car mon nombre ne dépasse jamais 1.500.000.000 ms ...

    J'ai un deuxième programme duquel je m'inspire qui stocke jusqu'à 50.000.000.000 dans un time_t mais quand je copie/colle le code dans mon programme ça ne marche pas

    Même lorsque je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    uint64 time = 31.536.000 * 1000);
    cout << time << endl;
    J'obtiens toujours un peu moins de 1.500.000.000, et pareil si je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cout << 31.536.000 * 1000;
    C'est incompréhensible ...

  2. #2
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Bonjour.

    Citation Envoyé par Nekkro Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cout << 31.536.000 * 1000;
    Rassure-moi...
    Tous les points que tu mets pour séparer les milliers, c'est juste pour nous, ils ne sont pas présents dans le programme que tu compiles ?

    Sinon, si tu ne précises rien, une constante anonyme entière est (par défaut) de type int.
    Le résultat d'une opération sur deux int est également un int.
    Et si transtypes le résultat d'une telle opération, le calcul sera d'abord fait sur des int, et donc potentiellement tronqué.

    Si tu veux un résultat qui n'est pas représentable avec un int, il faut transtyper au moins un des opérandes avant de faire l'opération.
    Lors d'une opération avec des types numériques différents, c'est le type plus large qui gagne.
    Essaie ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::cout << 31536000L * 1000 << std::endl;
    std::cout << 31536000000L << std::endl;
    // Ou avec UL si ça ne fonctionne pas
    De même, ce genre de choses devrait fonctionner :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    uint64 time = uint64(31536000) * 1000;
    std::cout << time << std::endl;
     
    //*********************//
     
    uint64 time = static_cast<uint64>( 31536000 ) * 1000;
    std::cout << time << std::endl;

  3. #3
    Membre du Club
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2011
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Août 2011
    Messages : 88
    Points : 65
    Points
    65
    Par défaut
    Avec ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    std::cout << 31536000UL * 1000 << std::endl;
    std::cout << 31536000000UL << std::endl;
    uint64 time = uint64(31536000) * 1000;
    std::cout << time << std::endl;
    uint64 utime = static_cast<uint64>( 31536000 ) * 1000;
    std::cout << utime << std::endl;
    J'obtiens ceci :
    1471228928
    31536000000
    31536000000
    31536000000

    Maintenant je vais préciser la chose. Cette valeur, je la récupère d'une table de base donnée MySQL, je fais donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    time_t get_time ()
    {
    	string val = value; // (value ==> const char*)
     
    	stringstream ss (val);
    	time_t time;
    	ss >> time;
    	return time;
    }
    Comment je peux adapter la conversion ici pour ne pas perdre de valeur ?

  4. #4
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Ah, ça ne marche pas directement ?
    Dans ce cas, essaie d'utiliser une variable auxiliaire de type (unsigned) long, ou plus grand si le compilateur le supporte, et fais un static_cast<time_t> pour le retour de la fonction.
    Ou alors fais un transtypage à la récupération de la valeur...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    unsigned long time;
    ss >> time;
    return static_cast<time_t>( time );
     
    //********************//
     
    time_t time;
    ss >> static_cast<unsigned long&>( time ); // Ou reinterpret_cast ?
    return time;

  5. #5
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Bonjour,

    std::cout << 31536000ULL * 1000 << std::endl;
    Devrait aider.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #include <iostream>
     
    int main()
    {
      std::cout << 31536000UL * 1000 << std::endl;
      std::cout << 31536000ULL * 1000 << std::endl;
    }
    Compilé avec g++ -o main main.cpp -m32 (parce que sinon, je suis en 64 bits)

    Donne
    1471228928
    31536000000
    UL est pour unsigned long (32 bits en architecture 32 bits); ULL est pour unsigned long long (64 bits en architecture 32 bits).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  6. #6
    Membre du Club
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2011
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Août 2011
    Messages : 88
    Points : 65
    Points
    65
    Par défaut
    En effet, tous les affichages marchent avec ULL.
    static_cast n'est pas accepté contrairement a reinterpret_cast qui fait carrément tout planter !

    J'ai tenté ceci : (from_string fais tout le passage avec stringstream)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    long long unsigned int time = from_string<long long unsigned int> (val);
    return static_cast<time_t> (time);
    Mais sans succès, pour 31.000.000.000 stocké en BDD, j'obtiens 935.228.928 en retour :/

    Pour
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    uint64_t time = from_string<uint64_t> (val);
    return static_cast<time_t> (time);
    J'ai un peu mieux, de l'ordre de 1.200.000.000 ... Mais je n'arrive pas encore à dépasser.

  7. #7
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Désolé, je ne vais pas pouvoir t'aider plus.
    Je peux juste te suggérer un truc, qui ne sera peut-être pas applicable selon ce que tu veux faire avec ces grands nombres.

    Tu peux essayer de casser ces nombres en deux parties : ce qui est supérieur à, disons 1.000.000, et ce qui inférieur (à toi de choisir la borne qui te paraît la plus appropriée).
    Ça donnerait quelque chose dans le genre :
    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
    class BigNumber
    {
     
      private:
        unsigned long m_high; // Pour le type, c'est encore un exemple
        usingned long m_low;
     
        (...)
     
      public:
        friend
        std::ostream& operator << (ostream& os, BigNumber const& n)
        {
            if (n.m_high > 0)
                os << n.m_high << std::setfill(0) << std::setw(6) << n.m_low;
            else
                os << n.m_low;
            return os 
        }
     
    };
    Ainsi, la valeur d'un BigNumber est en réalité m_high * 1000000 + m_low.
    Si tu n'as pas besoin de la vraie valeur numérique de ton grand nombre, je pense que ça peut suffire.

  8. #8
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par Nekkro Voir le message
    En effet, tous les affichages marchent avec ULL.
    static_cast n'est pas accepté contrairement a reinterpret_cast qui fait carrément tout planter !

    J'ai tenté ceci : (from_string fais tout le passage avec stringstream)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    long long unsigned int time = from_string<long long unsigned int> (val);
    return static_cast<time_t> (time);
    Mais sans succès, pour 31.000.000.000 stocké en BDD, j'obtiens 935.228.928 en retour :/

    Pour
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    uint64_t time = from_string<uint64_t> (val);
    return static_cast<time_t> (time);
    J'ai un peu mieux, de l'ordre de 1.200.000.000 ... Mais je n'arrive pas encore à dépasser.
    time_t est défini selon le système. Il est plus que probable que time_t soit un unsigned int, donc limité à 32 bits (alors que tu en souhaite 64) (c'est le cas sur gcc : time_t est un unsigned long int, donc 32 bits sur une plateforme 32 bits, et 64 bits sur une plateforme 64 bits).

    En conclusion, tu ne peux pas stocker ta valeur dans un time_t si tu es sur une plateforme 32 bits. Inutile que tu continue d'essayer : ta valeur est tronquée, de toute façon. Il faut que tu utilises un autre type, par exemple un extented_time_t défini ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    #include <stdint.h>
     
    typedef uint64_t extended_time_t;
    Il faudra probablement redéfinir les fonctions qui prennent un time_t pour accepter un extended_time_t, si tu te sers de certaines (sinon, abaondonne time_t directement, sans te poser de question).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  9. #9
    Membre du Club
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2011
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Août 2011
    Messages : 88
    Points : 65
    Points
    65
    Par défaut
    Le truc, c'est que je suis sous Windows 7 64 bit ^^"
    Et j'utilise GCC avec Code::Blocks.

    Ce qui m'étonne c'est que mon ami également sous 64 bit mais utilisant Visual Studio pour coder arrive à stocker au moins 50.000.000.000 dan un time_t !

    Ça me fait d'ailleurs penser à quelque chose :
    Lui n'a pas besoin d'include les fichiers du genre <windows.h> car, me dit-il, boost le fait automatiquement lorsque l'on est sous windows. Or moi cet include automatique ne se fait pas, je dois y aller manuellement. Est-ce que ça signifierait qu'il faut que je modifie des options dans CodeBlocks ou quelque part ailleurs, comme pour cette histoire de type de variable ?

    @Steph : ces grands nombres représentent un temps en millisecondes, et j'ai besoin de faire des opérations dessus, puis d'envoyer ce nombre via un packet. La seule solution que j'ai trouvé à l'heure actuelle et de mettre par exemple 50.000.000 dans ma BDD puis de rajouter "000" à la fin du nombre dans le packet pour récupérer la valeur en millisecondes. Malheureusement je perds en précision en faisant ça, et ça me gêne de "tricher", j'aimerais bien que ça marche normalement.

    J'ai également testé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    uint64_t time = Naia::from_string<uint64_t> (val);
    return static_cast<time_t> (time);
    Donc c'est mon time_t qui apparemment n'a pas la taille qu'il devrait avoir pour un 64bit, puisque j'ai le bon nombre dans time avant le cast.

    J'utiliserais donc uint64_t pour mes calculs.

  10. #10
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Citation Envoyé par Nekkro Voir le message
    Le truc, c'est que je suis sous Windows 7 64 bit
    Certes, mais ne serais-tu pas entrain de travailler avec un IDE/compilo 32 bits sous W64 bits? Pour moi le résultat dépend de l'architecture cible du compilateur, pas le l'architecture de l'hôte ou de l'OS...

  11. #11
    Membre du Club
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2011
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Août 2011
    Messages : 88
    Points : 65
    Points
    65
    Par défaut
    Dans ce cas, comment puis-je spécifier une compilation 64 bits ? (Ma recherche n'a rien donné).

  12. #12
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Alors:
    1. t'assurer que tu installes bien la version 64 bits de GCC (si packagé avec l'IDE,: vérifier la description du package, ça doit bien figurer quelque part)
    2. vérifier les options de compilation. Par défaut gcc 64 bits fait probablement du 64 bits, mais ça vaut le coup de préciser march=x86_64 ou quelque chose d'équivalent.

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 04/10/2007, 14h42
  2. Réponses: 2
    Dernier message: 16/04/2007, 11h53
  3. problème avec le séparateur de nombre décimal
    Par G_Kill dans le forum ASP.NET
    Réponses: 1
    Dernier message: 09/03/2007, 20h54
  4. Problème avec une petite fonction toute bête
    Par jeremy13 dans le forum MATLAB
    Réponses: 3
    Dernier message: 18/01/2007, 09h10
  5. Réponses: 3
    Dernier message: 10/05/2005, 11h02

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