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 :

Arrondir un double


Sujet :

C

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    plombier
    Inscrit en
    Décembre 2012
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : plombier
    Secteur : Bâtiment

    Informations forums :
    Inscription : Décembre 2012
    Messages : 31
    Points : 25
    Points
    25
    Par défaut Arrondir un double
    Bonjour, je suis en train de coder une calculatrice.

    Je me heurte à un problème un peu dérangeant pour une calculatrice.

    L’opération entrée par l’utilisateur est une chaine de caractère.
    Pour récupérer la partie entière du nombre, il n’y a pas de problème. Mon problème est pour la partie décimale.
    Exemple : 34.6598 de type char*
    Une foi récupéré caractère par caractère, ma variable de type double = 34.6598000000000002

    Je cherche donc :

    Comment éviter cette imprécision ? Ou alors comment arrondir un double 9 chiffres après la virgule sans les convertir en un entier ?

    Merci d’avance

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Tu ne peux pas éviter cette imprécision. Elle est liée à la nature même d'un nombre flottant à double précision.
    La seule solution, très désagréable, d'ailleurs, c'est de travailler avec des chaines de caractères représentant les nombres.
    Cela veut dire réécrire les mathématiques, et payer surcoût en performance (qui est énorme).

    Mais même les calculatrices modernes et les professionnels (comme Calc ou Excel) accepte cette erreur.

    L'influence est mineure.
    Dans ton exemple, l'erreur est de 2*10E-17, soit 20 milliardièmes de milliardièmes. comparé à une valeur de 34 et des bananes, c'est un ratio de 10E-18.

    En physique, on parlerait de "négligeable" car, 1 sur l'infini = 0.
    Car oui, l'infini en physique, c'est trois ordres de grandeur au-dela des valeurs abordées: parlant d'un escargot, une tonne, un million de tonne ou le Soleil, c'est la même masse.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    Bonjour,

    Citation Envoyé par Dev 37C Voir le message
    Comment éviter cette imprécision ? Ou alors comment arrondir un double 9 chiffres après la virgule sans les convertir en un entier ?
    Avec printf, tu peux arrondir tes nombres :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("%.4f", my_number); // arrondi a 4 chiffres

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    plombier
    Inscrit en
    Décembre 2012
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : plombier
    Secteur : Bâtiment

    Informations forums :
    Inscription : Décembre 2012
    Messages : 31
    Points : 25
    Points
    25
    Par défaut
    Citation Envoyé par leternel Voir le message
    Tu ne peux pas éviter cette imprécision. Elle est liée à la nature même d'un nombre flottant à double précision.
    La seule solution, très désagréable, d'ailleurs, c'est de travailler avec des chaines de caractères représentant les nombres.
    Cela veut dire réécrire les mathématiques, et payer surcoût en performance (qui est énorme).

    Mais même les calculatrices modernes et les professionnels (comme Calc ou Excel) accepte cette erreur.
    Merci pour vos réponses. Ma question est pourquoi?? d'ou vient cette perte de précision??

    Bonne soiree

  5. #5
    Invité
    Invité(e)
    Par défaut
    Elle vient de la manière même dont est encodé un nombre en mémoire.

    Comment les nombres sont encodé dans un ordinateur actuellement ? En binaire.
    Pourquoi ? Car ce qui est intéressant en binaire, ce sont ces puissances. Les puissances de 2 permettent tout simplement de représenter n'importe quel nombre entier avec une étonnante facilité.
    Ainsi, par exemple, une variable codé sur 8bits représente une capacité de 2 puissance 8 (2^8), soit 2x2x2x2x2x2x2x2 = 256 possibilités. un nombre encodé sur 16bits aura lui, suivant le même principe, 2^16 possibilité, soit 65536 possibilités. Le nombre de bits permet donc d'augmenter le domaine des possibles absolument faramineux.

    Prenons pour exemple le chiffre 23.

    Si on le décompose en binaire, cela nous donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        1 x 2^0  -- 1
    +   1 x 2^1  -- 2
    +   1 x 2^2  -- 4
    +   0 x 2^3  -- 0
    +   1 x 2^4  -- 16
    -----------------------
          10111  -- 23
    Simple, facile, efficace.

    C'est trop beau pour être vrai, n'est-il pas ? Ou est le hic ?
    Les nombres réels sont la grosse écharde dans le pied velu des ordinateurs. Pourquoi ?

    Tout est encodé en binaire, les nombres réels aussi. Comment représenter alors "une virgule" en binaire ? On va utiliser le même principe que pour des nombres entiers.. On va le décomposer. Sauf que cette fois, au lieu de décomposé avec des puissances positives, on va utiliser des puissances négatives. Pourquoi ? Car les puissances négative vont nous donner un nombre compris entre 0 et 1 ... Exactement ce que sont les chiffres après la virgule donc.

    Ainsi, pour représenter le nombre 23.625, on va décomposer la partie entière et la partie réel différemment :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        1 x 2^-1  -- 0.5
    +   0 x 2^-2  -- 0
    +   1 x 2^-3  -- 0.125
    -----------------------
             101  -- 0.625
    On peut donc dire que le nombre 23.625 sera codé : 10111.101

    Cela parait simple, il est vrai... Maintenant, que se passe t'il si l'on veut non plus 23.625, mais 23.626 ? Il n'y a que 0.001 de différence après tout, ce n'est pas énorme... Et pourtant. Il faut nous trouver les 0.001 restant... Mais où ?
    Et c'est là que le problème devient épineux. Plus on descends dans les puissances négatives de 2, plus les nombres deviennent petit... Sans pour autant nous permettre de compléter ce petit 0.001 manquant. il faudrait énormément de bits pour permettre à la machine de descendre assez profondément dans les puissances négatives pour trouver le nombre correct à 100%, sans pour autant que cela soit possible.

    A partir de ce constat, il a été décidé d'instaurer un "type standard", qui permettrait au mieux de rendre compte des nombres réels, tout en acceptant une possibilité d'imprécision minime. Il s'agit du fameux type "double" du C. Ce type ne fonctionne pas exactement comme je l'ai décrit plus haut, mais il est une résultante de cette idée. Je peux t'inviter à regarde ici pour plus de précisions : http://cpp.developpez.com/redaction/...ant/flottant1/

    Tu pourrais te demander : " mais pourquoi ne pas simplement considérer la partie réel comme étant des nombres entier, et les considérer comme tel ? "
    Et c'est effectivement une bonne question. Certaine bibliothèque spécialisé procède ainsi. Mais cette précision a un prix; la taille prise en mémoire pour représenter un nombre ainsi constitué est colossale en comparaison d'un nombre réel "normal". On n'utilise ce genre de bibliothèque où la précision est primordiale, je pense par exemple au domaine comptable. Pour une utilisation plus "courante", le meilleur rapport qualité/utilisation reste le type standard.
    Dernière modification par Invité ; 24/03/2015 à 12h27. Motif: bourde dans [code]

Discussions similaires

  1. Arrondir un double
    Par kheira dans le forum C++Builder
    Réponses: 11
    Dernier message: 20/04/2010, 13h35
  2. Arrondir un double
    Par arcanis dans le forum Débuter
    Réponses: 8
    Dernier message: 07/11/2009, 18h36
  3. arrondir un double
    Par mkachakh dans le forum Général Java
    Réponses: 1
    Dernier message: 27/02/2008, 12h08
  4. Comment arrondir un Double à l'excès ?
    Par vitch8 dans le forum Langage
    Réponses: 3
    Dernier message: 17/01/2008, 10h39
  5. arrondir reel double MSHFLEXGRID
    Par totoche dans le forum VB 6 et antérieur
    Réponses: 9
    Dernier message: 27/09/2006, 16h27

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