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 :

Précision des nombres à virgule


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Avatar de Wachter
    Homme Profil pro
    Développeur
    Inscrit en
    Octobre 2008
    Messages
    404
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Octobre 2008
    Messages : 404
    Par défaut Précision des nombres à virgule
    Bonjour,

    Je cherche à encoder et à manipuler des nombres de cette précision (30 chiffres environ après la virgule) :
    A = 0,84965724432017509411832466764058
    B = 0,34929922307744668373624877606906
    C = 1,6013793132890827397668320682411

    J'utilise le type long double, je réalise plusieurs multiplications et divisions sur des nombres d'une même précision. Au bout de quelques itérations, les résultats sont faussés à cause des valeurs tronquées à mon avis...

    Le type long double a une précision de 15 chiffres je crois. Ma question est de savoir quel type utiliser pour gérer cette grande précision.

  2. #2
    Expert confirmé

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

    La bibliothèque GMP, plus connue pour les calculs sur des entiers de longueur quelconque, comprend également une section pour les calculs sur les nombres flottants.

    %Ais quoi qu'il en soit, ne te fait pas d'illusion, les arrondis, et donc les erreurs, sont inévitables, et finiront par te rattraper, même si on peut repousser la limite (mais c'est au prix du temps de calcul ...).


  3. #3
    Membre éclairé
    Avatar de Wachter
    Homme Profil pro
    Développeur
    Inscrit en
    Octobre 2008
    Messages
    404
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Octobre 2008
    Messages : 404
    Par défaut
    Merci pour ta réponse. J'espère que l'utilisation de cette bibliothèque n'est pas très compliquée...

    Par ailleurs, je récupère le nombre en question à partir d'un TEdit en utilisant la fonction StrToFloat. Je me pose aussi la question si cette fonction de conversion ne pose pas de problème de précision...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    long double nombre = StrToFloat(EditNombre->Text);

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Si surement, vu qu'il n'y a que certains chiffres qui sont exactement représentables, et ils sont en nombre finis et loin de représenter tout ton ensemble.
    Si tu travailles sur des valeurs fixes de digits après la virgule, travaille en entier et fais une division finale. Ou mieux, garde tout en entier et représente-les juste à virgule à la fin si/quand nécessaire.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Membre éclairé
    Avatar de Wachter
    Homme Profil pro
    Développeur
    Inscrit en
    Octobre 2008
    Messages
    404
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Octobre 2008
    Messages : 404
    Par défaut
    Tu as raison, je vais opter pour cette solution : travailler sur des entiers et afficher le résultat en nombre flottant à la fin. Je dois conserver au moins 21 chiffres après la virgule.

    Juste une dernière question : vu qu'il y a une interface utilisateur, je dois récupérer le nombre flottant saisi par l'utilisateur sous la forme d'une chaîne de caractères (1,123456789123456789123, par exemple). Le fait de convertir la chaîne avec StrToFloat tronque-t-il la valeur exacte du nombre de départ ?

  6. #6
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Citation Envoyé par Wachter Voir le message
    Juste une dernière question : vu qu'il y a une interface utilisateur, je dois récupérer le nombre flottant saisi par l'utilisateur sous la forme d'une chaîne de caractères (1,123456789123456789123, par exemple). Le fait de convertir la chaîne avec StrToFloat tronque-t-il la valeur exacte du nombre de départ ?
    Si StrToFloat retourne un float sur moins de ~128bits oui. Et vu que les float128 ne sont pas standards, il est plus que probable que tu perde de la précision ici. (Et je suis même pas sur qu'un float128 puisse fournir cette précision).
    Fait la conversion à la main.

  7. #7
    Expert confirmé

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

    Oui, les float (4 octets) ne garantissent que 5 à 6 chiffres significatifs, les double 15 à 16.

    Tu n'as donc pas le choix, il faut utiliser la bibliothèque en question, y compris ses fonctions de conversion !

  8. #8
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Janvier 2003
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations forums :
    Inscription : Janvier 2003
    Messages : 4
    Par défaut
    La solution de Bousk est la plus simple, utilise des nombres entiers pour tout ce qui est manipulation tant que tu connais combien de chiffres apres la virgule tu as besoin.
    GMP (https://gmplib.org/) peut etre utilisée si ton projet accepte la license GPLv2 ou LGPLv3 (mais ça c'est un autre sujet de discussion).
    Une autre solution, bien moins elegante est de convertir en string et definir tes operations, c'est tres laborieux speciallement si tu dois supporter modulo, multiplication, etc.

  9. #9
    Membre éclairé
    Avatar de Wachter
    Homme Profil pro
    Développeur
    Inscrit en
    Octobre 2008
    Messages
    404
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Octobre 2008
    Messages : 404
    Par défaut
    Citation Envoyé par Jerome2568 Voir le message
    La solution de Bousk est la plus simple, utilise des nombres entiers pour tout ce qui est manipulation tant que tu connais combien de chiffres apres la virgule tu as besoin.
    J'ai 24 chiffres après la virgule ; comment les stocker dans un int / long int ?

  10. #10
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 967
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 967
    Par défaut
    Bonjour,
    Citation Envoyé par Wachter Voir le message
    J'ai 24 chiffres après la virgule ; comment les stocker dans un int / long int ?
    Tu tournes en rond avec le même problème : tes exigences dépassent la capacité des types standards, tu n'échapperas pas à une bibliothèque spécialisée.

  11. #11
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 760
    Par défaut
    int128_t, certain compilateur le supporte (tous ?). Sinon, des bibliothèques comme boost.cpp_int.

  12. #12
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Citation Envoyé par Wachter Voir le message
    J'ai 24 chiffres après la virgule ; comment les stocker dans un int / long int ?
    La question n'a pas de sens, c'est comme demander "J'utilise des nombres de 0 à 152, comment je stocke ça dans un bool ?" Tu peux essayer tout ce que tu veux, ça rentre pas.

    C'est pareil ici, 24 chiffres significatifs ça rentre pas dans des float / double / long double / int / long long.
    Il faut plus gros (int128 ou float128).

  13. #13
    Membre éclairé
    Avatar de Wachter
    Homme Profil pro
    Développeur
    Inscrit en
    Octobre 2008
    Messages
    404
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Octobre 2008
    Messages : 404
    Par défaut
    Je répondais à la personne qui m'avait proposé de manipuler des entiers...

    Mon programme compile une fois sur deux avec Code::Blocks. Le type float128 n'est finalement pas précis.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    #include <iostream>
    #include <boost/multiprecision/float128.hpp>
     
    int main()
    {
       boost::multiprecision::float128 nb;
     
       nb = 0.34929922307744668373624877606906;
       nb = nb * 125;
       std::cout << std::setprecision(32) << nb << std::endl;
     
       return 0;
    }
    Affiche : 43,662402884680838466291419308618

    Avec ma calculatrice j'obtiens : 43,662402884680835467031097008633

  14. #14
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Toujours le même problème, tu perds ta précision quelque part. Ici tu la perds lors de la construction de nb.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    boost::multiprecision::float128 nb;
     
    nb = 0.34929922307744668373624877606906; // 0.349... est un double -> perte de précision
     
    nb = boost::multiprecision::float128("0.34929922307744668373624877606906"); // ok, construction depuis un string
    nb = 0.34929922307744668373624877606906Q; // ok, 0.349... est un float128

Discussions similaires

  1. Réponses: 64
    Dernier message: 14/02/2011, 14h02
  2. stockage des nombres à virgule flottante
    Par Alexdezark dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 24/11/2008, 10h43
  3. Réponses: 3
    Dernier message: 03/08/2007, 09h06
  4. [VBA-Excel] Tri de listview ne fonctionne pas avec des nombres à virgule
    Par marsupilami34 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 12/09/2006, 15h32
  5. additionner des nombres à virgules
    Par Phiss dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 22/03/2006, 10h35

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