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 :

petit problème de calcul flottant


Sujet :

C

  1. #1
    Membre confirmé Avatar de fred_sell
    Inscrit en
    Juin 2009
    Messages
    106
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 106
    Par défaut petit problème de calcul flottant
    bonsoir

    voilà je voudrais savoir pourquoi la condition çi-dessous est fausse, regardez :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    float x=12.5;
     
    x-=12;
     
    if(x==0.5)    // cette condition est fausse ?? 12.5-12 = 0.5 !!! n'est ce pas !!
    {
            ...........   //j'ai deja essayé : la condition est fausse
    }
    pourquoi ? est ce que cela est-il dù à l'incertitude, est ce qu'on devra en prendre compte ?

    merci infiniment d'avance !!!

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 496
    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 496
    Par défaut
    Bonjour,

    Ça marche bien chez moi (gcc 4.4.4 64 bits). En plus, 12,5 est un nombre fini en binaire, « 1100,1 », donc il n'y a pas d'imprécision due au format.

    Quel compilateur utilises-tu et sur quelle plateforme ?

  3. #3
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 157
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 157
    Billets dans le blog
    151
    Par défaut
    Bonjour,

    Un meilleur code ne serait il pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    float x=12.5f;
    
    x-=12;
    
    if(x==0.5f) 
    {
    
    }
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  4. #4
    Membre confirmé Avatar de fred_sell
    Inscrit en
    Juin 2009
    Messages
    106
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 106
    Par défaut
    d'ou vient ce f, je l'ai jamais vu !!

    quel est mon problème au juste ??

  5. #5
    Invité
    Invité(e)
    Par défaut
    Et si tu fais :

  6. #6
    Membre confirmé Avatar de fred_sell
    Inscrit en
    Juin 2009
    Messages
    106
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 106
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Bonjour,

    Ça marche bien chez moi (gcc 4.4.4 64 bits). En plus, 12,5 est un nombre fini en binaire, « 1100,1 », donc il n'y a pas d'imprécision due au format.

    Quel compilateur utilises-tu et sur quelle plateforme ?

    moi c ----> (gcc, 32 bits) !!

  7. #7
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par fred_sell Voir le message
    d'ou vient ce f, je l'ai jamais vu !!
    Ce f signifie que le nombre est un float.

    12.5f est un float alors que 12.5 est un double (qui sera converti en float lors de l'affectation).

  8. #8
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    J'avoue que moi non plus, je n'avais jamais vu une écriture du genre
    float x=12.5f;
    Par contre la comparaison (==) de 2 float a généralement peu de chance de marcher. Par principe et par habitude, il faut écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if (fabs(x - 0.5) < 1.e-5)
    {
      ...
    }
    J'ai choisi 1.e-5, mais cela dépend de la précision.
    On pourrait se dire, autant travailler en int ou en long, par exemple en centimes. C'est souvent une bonne méthode.
    S'il s'agit de coordonnées, le programme va probablement faire des opération autres que des additions et des soustractions. Donc il est probable que le même problème se présente aussi, même pour des valeurs entières.
    Le test "==" doit être réservé aux cas où on est sûr que le valeurs sont strictement égales.
    Cordialement.

  9. #9
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Avec ou sans f, le code présenté par le posteur doit donner VRAI comme résultat de la comparaison et Obsidian , plus haut, a bien expliqué pourquoi.

  10. #10
    Invité
    Invité(e)
    Par défaut
    Oui, 12.5 est un nombre fixe, si on fait le test
    if (x == 12.5) //on obtiendra VRAI parce que X est EXACTEMENT égal à 12.5.

    Maintenant,
    x -= 12.0;
    if (x == 0.5) //on obtiendra généralement FAUX parce que X est à peu près égal à 0.5.

    C'est à dire que dans le cas général où le test de comparaison ne sera pas fait pour savoir si x a été modifié, mais pour comparer la valeur de x à quelque-chose, il faudra faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if ( fabs(x-0.5) <= 1.E-5)
    {
    ...
    }

  11. #11
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Pierre Dolez Voir le message
    Oui, 12.5 est un nombre fixe, si on fait le test
    if (x == 12.5) //on obtiendra VRAI parce que X est EXACTEMENT égal à 12.5.

    Maintenant,
    x -= 12.0;
    if (x == 0.5) //on obtiendra généralement FAUX parce que X est à peu près égal à 0.5.
    Ah bon? Tu peux m'expliquer en detail pourquoi?

    A mon avis, 12.5, 12 et 0.5 etant exactement representables dans les formats de flottants habituels (... en fait, dans tous les formats flottants ayant reellement ete utilises que je connais, y compris les plus tordus), le calcul sera exact. Il y a eu quelques implementations ne donnant pas toujours un resultat exact dans ce genre de circonstances pour la division, mais je n'ai jamais entendu dire que ce fut jamais le cas pour l'addition ou la soustraction.

  12. #12
    Invité
    Invité(e)
    Par défaut
    Soit, vous avez parfaitement raison avec la soustraction.
    Il n'en reste pas moins vrai qu'il ne faut en général pas compter avec une EGALITE entre 2 float.
    La plupart du temps, si on travaille en float voire an double, c'est parce qu'il y a de nombreuses décimales.
    Je suppose que si fred-sell a posé la question, c'est qu'il a rencontré le problème. Le code qu'il a montré est un exemple théorique. Dans la pratique, on ne fait pas ce type de calcul avec une grosse machine, mais la valeur de x est lue sur un fichier, on fait des opérations sur cette valeur, et pas seulement une soustraction simple etc etc.
    Donc si on ne fait pas la comparaison comme je l'ai montré, on est sûr de se planter, mais on n'est pas sûr de le voir tout de suite, c'est pourquoi, il FAUT bannir les comparaisons de float avec "==".

    Remarque de langage : quand je dit que x est "à peu près égal à" 0.5, une valeur float étant sur 32 bits, ce qui donne 7 chiffres significatifs, le huitième est forcément faux, mais la valeur avec 6 chiffres significatifs est juste, le 7è étant aléatoire.
    Donc un flotant n'est JAMAIS exact, par définition, il y a d'ailleurs bien des cas où si on lit 1.0 sur un fichier et qu'on l'imprime, on risque bien d'avoir 0.9999998.
    Si vous dites le contraire vous induisez en erreur beaucoup de jeunes programmeurs.

  13. #13
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Pierre Dolez Voir le message
    Il n'en reste pas moins vrai qu'il ne faut en général pas compter avec une EGALITE entre 2 float.
    En général il faut se méfier des affirmations tranchées sur les flottants: elles sont fausses.

    La plupart du temps, si on travaille en float voire an double, c'est parce qu'il y a de nombreuses décimales.
    S'il faut de nombreuses décimales, je conseille fortement d'éviter les floats et les doubles risquent d'être limites.

    Donc si on ne fait pas la comparaison comme je l'ai montré, on est sûr de se planter,
    Si on la fait comme tu l'as montré, on est tout aussi sûr de se planter. Il faudrait au strict minimum indiquer pourquoi tu as choisi 1E-5. Dans le cas présent c'est un nombre tombé d'on ne sait où. Il va être ajusté au petit bonheur la chance pour faire passer quelques exemples sans qu'on ait la moindre indication de pourquoi c'est la bonne valeur -- enfin... dans le cas improbable où c'est une valeur sensée.

    il FAUT bannir les comparaisons de float avec "==".
    Si tu penses cela, je te défends d'enlever les égalités de flottants quand j'en écris. Pour commencer, si j'ai besoin du fait que ma relation d'égalité doit être une relation d'équivalence, je fais quoi?

    Remarque de langage : quand je dit que x est "à peu près égal à" 0.5, une valeur float étant sur 32 bits, ce qui donne 7 chiffres significatifs, le huitième est forcément faux, mais la valeur avec 6 chiffres significatifs est juste, le 7è étant aléatoire.
    On n'est d'accord sur a peu près rien. Pour les float sur 32 bits au format IEEE, le parcours format decimal-float-format decimal est garanti sans perte jusqu'à 6 chiffres décimaux. Mais ça ne veut certainement pas dire qu'une représentation décimale avec plus de chiffres a des chiffres "faux" ou "aléatoire", du moins si elle est bien faite.

    Donc un flotant n'est JAMAIS exact, par définition, il y a d'ailleurs bien des cas où si on lit 1.0 sur un fichier et qu'on l'imprime, on risque bien d'avoir 0.9999998.
    Si vous dites le contraire vous induisez en erreur beaucoup de jeunes programmeurs.
    <coup de gueule hint="t'est pas visé personnellement">

    Les calculs sur les flottants peuvent être exacts. C'est en disant le contraire qu'on induit en erreur les jeunes programmeurs.

    La première chose à comprendre, c'est que les flottants ne sont pas des réels et ne se comportent pas comme eux.

    Et j'en ai marre de ceux qui ayant compris cela s'arrêtent et ne vont pas plus loin, pensent les flottants sont des choses bizarres incompréhensibles où les erreurs apparaissent aléatoirement et qui ne peuvent être maîtrisées que par des techniques de programmation superstitieuses.

    Donc la deuxième chose à comprendre, c'est que des trucs simples ne suffisent pas à permettre de manipuler les flottants sans problèmes. Dire qu'il ne faut jamais utiliser l'égalité mais une comparaison d'intervalle sans indiquer comment calculer l'intervalle (*), sans indiquer que le résultat n'est pas une relation d'équivalence (propriété que la plupart des gens suppose quand on leur donne une relation sensée remplacer l'égalité) c'est pas rendre service. Le penser, c'est s'illusionner.

    La troisième chose à comprendre, c'est que l'arithmétique sur les flottants si elle n'obéit pas aux même règles que l'arithmétique sur les réels obéit quand même à des règles déterministes. On peut les maîtriser. On peut borner la différence entre le résultat obtenu en utilisant les flottants et celui qu'on aurait obtenu avec les réels. On peut améliorer ces bornes en faisant attention et en utilisant des techniques qui peuvent sembler bizarres ou inutiles (mais qui elles ne tiennent pas de la superstition).

    (*) Ou pire comme je l'ai déjà vu en proposant des manières de calculer l'intervalle qui n'ont absolument aucun sens, retournant toujours vrai dès que les deux nombres sont trop petits, retournant toujours faux dès qu'ils sont trop grands.

    </coup de gueule>

  14. #14
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 398
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    La première chose à comprendre, c'est que les flottants ne sont pas des réels et ne se comportent pas comme eux.
    Je plussoie comme c'est pas permis. C'est pourquoi je déteste les langages qui utilisent des flottants et les appellent "real".
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  15. #15
    Invité
    Invité(e)
    Par défaut
    Oui, mais je pense que ça intéresserait la communauté et moi en particulier de connaitre la nuance, et surtout les implication en matière de logique et de programmation.

  16. #16
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145

  17. #17
    Invité
    Invité(e)
    Par défaut
    Merci pour les lins, je vais lire tout ça.
    J'en ai un autre en rapport direct avec ce sujet :
    http://c.developpez.com/faq/index.ph...AT_comparaison

    PS celui-là est écrit en français.
    Pour les 3 autres liens, certainement parfait pour la théorie, mais j'avoue que je n'ai fait qu'un survol très rapide.
    Dernière modification par Invité ; 02/07/2010 à 14h52.

  18. #18
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 398
    Par défaut
    Wow, ce document jette la honte sur Melem. Il n'y a pas de réels en C.

    Par contre, la suite est intéressante, avec le calcul d'un epsilon approprié...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  19. #19
    Invité
    Invité(e)
    Par défaut
    Oui mais dans la pratique : QUE DOIT-ON FAIRE ou NE PAS FAIRE.
    Je pense que c'est ça qui intéresse les développeurs en C.
    Un ou deux exemple s'il vous plait.

  20. #20
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Pierre Dolez Voir le message
    Oui mais dans la pratique : QUE DOIT-ON FAIRE ou NE PAS FAIRE.
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Donc la deuxième chose à comprendre, c'est que des trucs simples ne suffisent pas à permettre de manipuler les flottants sans problèmes.
    Il y a quand meme vraisemblablement moyen d'ecrire quelque chose de plus simple que ce qu'il y a dans les liens que j'ai donne, mais je ne connais pas de documents de cette sorte (j'ai un peu cherche pas pas trop). J'ai un vague projet d'un ecrire un, mais meme si j'en trouve le temps (ce n'est jamais qu'en position 3 ou 4 sur ma liste de choses a faire de ce genre) ca sera quand meme trop long et trop mathematique pour ceux qui cherchent des recettes simples a appliquer sans reflechir.

Discussions similaires

  1. [Toutes versions] Petit problème de calcul de temps.
    Par DenisHen dans le forum Macros et VBA Excel
    Réponses: 33
    Dernier message: 13/05/2015, 08h21
  2. Réponses: 11
    Dernier message: 19/09/2010, 14h37
  3. Batch - Petit probléme de calcule
    Par Lorponos dans le forum Windows
    Réponses: 9
    Dernier message: 22/07/2006, 11h48
  4. [jointure] Petit problème sur le type de jointure...
    Par SteelBox dans le forum Langage SQL
    Réponses: 13
    Dernier message: 13/02/2004, 18h55
  5. Calcul flottant
    Par Cold Hand dans le forum x86 32-bits / 64-bits
    Réponses: 4
    Dernier message: 10/02/2004, 17h51

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