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 :

Question sur les flottants


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut Question sur les flottants
    Salux,

    Un truc me tracasse depuis longtemps, on sait qu'un flottant n'a pas de valeur absolument determinée et si j'ai bien compris, 3.0 peut valoir en realité 2.99999 ou 3.000001.
    C'est qd meme important de savoir si c'est 2.9999 ou 3.0001 lorsqu'on transtype en entier car dans un cas ça donne 2 et dans l'autre ça donne 3.

    Ma question est : est-ce qu'on peut assumer que les fonctions ceil et floor renvoient un flottant forcement legerement supérieur à la valeur entière resultat? est ce que ceil(2.1) vaut toujours 3.00000000001 ?

    Mercix

  2. #2
    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 Gruik
    Un truc me tracasse depuis longtemps, on sait qu'un flottant n'a pas de valeur absolument determinée
    Si.

    et si j'ai bien compris, 3.0 peut valoir en realité 2.99999 ou 3.000001.
    Les entiers sont exactement representables dans tous les formats de flottants que je connais. Autrement dit 3.0 sera toujours 3.0.

  3. #3
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    Si.



    Les entiers sont exactement representables dans tous les formats de flottants que je connais. Autrement dit 3.0 sera toujours 3.0.
    Mais 3.0 ne sera jamais 3, c'est ça?

  4. #4
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    En tous cas, Jean-Marc, pour terminer là dessus, ta première réponse est effectivement fausse par rapport à la question originale :

    Citation Envoyé par Gruik
    Un truc me tracasse depuis longtemps, on sait qu'un flottant n'a pas de valeur absolument determinée
    Citation Envoyé par Jean-Marc.Bourguet
    Si.

    Les entiers sont exactement representables dans tous les formats de flottants que je connais. Autrement dit 3.0 sera toujours 3.0.
    et la norme définit correctement une précision en deçà de laquelle il n'est pas possible de spécifier avec exactitude que le résultat d'un calcul qui devrait donner 2.0 ne donnera pas forcément 2.0... mais 2.0 +- DBL_EPSILON.

    Et d'ailleurs la question n'était pas par rapport aux entiers, mais aux flottants, ce dont on vient de parler pendant le thread.

    En dehors de ça, nous sommes d'accord.

  5. #5
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par souviron34
    En tous cas, Jean-Marc, pour terminer là dessus, ta première réponse est effectivement fausse par rapport à la question originale :





    et la norme définit correctement une précision en deçà de laquelle il n'est pas possible de spécifier avec exactitude que le résultat d'un calcul qui devrait donner 2.0 ne donnera pas forcément 2.0... mais 2.0 +- DBL_EPSILON.

    Et d'ailleurs la question n'était pas par rapport aux entiers, mais aux flottants, ce dont on vient de parler pendant le thread.

    En dehors de ça, nous sommes d'accord.
    Selon ce que j'ai compris des remarques de Jean-Marc Bourguet, la norme impose que le système de représentation des nombres flottant soit capable de représenté de manière exacte n'importe quel entier. Je ne m'y connais pas trop, mais il semble que cela soit le cas avec IEEE 754 où il me semble que tous les entiers de type int peuvent être représentés de manière exacte par un flottant double précision. En particulier, les entiers 2.0, 3.0, et 6.0 sont représentable exactement. Donc, le calcul 2.0 * 3.0 est également représentable exactement, et je crois que c'est garantit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    La représentation IEEE 754 de 2.0 est:
    0100000000000000000000000000000000000000000000000000000000000000
    ---------------------------------------
    La représentation IEEE 754 de 3.0 est:
    0100000000001000000000000000000000000000000000000000000000000000
    ---------------------------------------
    La représentation IEEE 754 de 2.0 est:
    0100000000000000000000000000000000000000000000000000000000000000
    ---------------------------------------
    La représentation IEEE 754 de 6.0 est:
    0100000000011000000000000000000000000000000000000000000000000000
    ---------------------------------------
    La représentation IEEE 754 de 2.0 * 3.0 est:
    0100000000011000000000000000000000000000000000000000000000000000
    Donc, si j'ai bien compris ce qui a été dit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    a = 2.0 * 2.2;
     
    if (a == 4.4)
    {
         /* traitement */
    }
    N'est pas garantit de fonctionner car 2.2, ni 4.4 ne sont représentablesexactement. Par contre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    a = 2.0 * 3.0;
     
    if (a == 6.0)
    {
        /* Traitement */
    }
    est garantit de fonctionner!

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  6. #6
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par mujigka
    . Par contre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    a = 2.0 * 3.0;
     
    if (a == 6.0)
    {
        /* Traitement */
    }
    est garantit de fonctionner!

    Thierry
    Non...

    Ce que la norme dit, c'est que :

    si tu fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    a = 6.0
    if ( a == 6.0 )
    ça marche.

    Par contre, a étant une variable, si a est le résultat d'un calcul, et que sa valeur devrait être 6.0, tester

    a une chance sur 20 millions de milliards de marcher (en prenant la valeur IEEE de 10e-16).

  7. #7
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Oui, mais la quiestion de Gruik était:
    Citation Envoyé par Gruik
    Ma question est : est-ce qu'on peut assumer que les fonctions ceil et floor renvoient un flottant forcement legerement supérieur à la valeur entière resultat? est ce que ceil(2.1) vaut toujours 3.00000000001 ?
    Dans le cas de ceil() et floor(), on est garantit d'obtenir une valeur entière représentable exactement, non? Chez moi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    double x = floor(20.0/3.0); /* 6.6666<...> */
    if (x == 6.0)
    {
        /* Traîtement */
    }
    la condition du if est vraie, et je pense que c'est toujours le cas (au vue de ce que j'ai pu lire dans ce fil).

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  8. #8
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    La norme n'impose rien sur les calculs en flottants, mais IEEE754 impose plus. Je me place dans ce dernier cadre (hors IBM et ses flottants a base hexadecimale et les cas particuliers des denormaux, les flottants non IEEE n'ont plus qu'un interet anecdotique).

    Citation Envoyé par mujigka
    Selon ce que j'ai compris des remarques de Jean-Marc Bourguet, la norme impose que le système de représentation des nombres flottant soit capable de représenté de manière exacte n'importe quel entier.
    ... de taille raisonnable evidemment.

    Non seulement la norme C l'impose, mais je ne connais aucun format qui ne le permette pas.

    Je ne m'y connais pas trop, mais il semble que cela soit le cas avec IEEE 754 où il me semble que tous les entiers de type int peuvent être représentés de manière exacte par un flottant double précision.
    Pas si tu as un int 64 bits. Mais de telles implementations sont rares.

    En particulier, les entiers 2.0, 3.0, et 6.0 sont représentable exactement. Donc, le calcul 2.0 * 3.0 est également représentable exactement,
    La norme C n'impose rien sur les calculs. La norme IEEE impose que le resultat soit correctement arrondi (et permet de choisir entre 4 modes d'arrondi: au plus proche, vers 0, vers +l'infini, vers -l'infini).

    et je crois que c'est garantit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    La représentation IEEE 754 de 2.0 est:
    0100000000000000000000000000000000000000000000000000000000000000
    ---------------------------------------
    La représentation IEEE 754 de 3.0 est:
    0100000000001000000000000000000000000000000000000000000000000000
    ---------------------------------------
    La représentation IEEE 754 de 2.0 est:
    0100000000000000000000000000000000000000000000000000000000000000
    ---------------------------------------
    La représentation IEEE 754 de 6.0 est:
    0100000000011000000000000000000000000000000000000000000000000000
    ---------------------------------------
    La représentation IEEE 754 de 2.0 * 3.0 est:
    0100000000011000000000000000000000000000000000000000000000000000
    Donc, si j'ai bien compris ce qui a été dit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    a = 2.0 * 2.2;
     
    if (a == 4.4)
    {
         /* traitement */
    }
    N'est pas garantit de fonctionner car 2.2, ni 4.4 ne sont représentablesexactement.
    Gagne.

    Par contre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    a = 2.0 * 3.0;
     
    if (a == 6.0)
    {
        /* Traitement */
    }
    est garantit de fonctionner!
    Par la combinaison norme C, norme IEEE 754, oui.

  9. #9
    Membre expérimenté
    Inscrit en
    Décembre 2003
    Messages
    272
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 272
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    La norme n'impose rien sur les calculs en flottants, mais IEEE754 impose plus. Je me place dans ce dernier cadre (hors IBM et ses flottants a base hexadecimale et les cas particuliers des denormaux, les flottants non IEEE n'ont plus qu'un interet anecdotique).
    Il me semble que le format interne du coprocesseur Intel est différent (même si il n'est pas vraiment accessible en C).
    (source : http://beuss.developpez.com/tutoriels/pcasm/).

  10. #10
    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 souviron34
    et la norme définit correctement une précision en deçà de laquelle il n'est pas possible de spécifier avec exactitude que le résultat d'un calcul qui devrait donner 2.0 ne donnera pas forcément 2.0... mais 2.0 +- DBL_EPSILON.
    Premierement, un des points que j'essaie de faire est que, par definition de DBL_EPSILON, pour un format binaire, entre 2.0-DBL_EPSILON et 2.0+DBL_EPSILON, bornes comprises, il n'y a qu'un nombre representable en flottant: 2.0. Quand on utilise DBL_EPSILON, il faut le mettre a l'echelle.

    Deuxiemement, il faut savoir de quel calcul tu parles.

    Si tu fait 2050.1 - 2048.1, l'erreur peut etre environ 1000 fois plus grande que si tu fais 4.1-2.1. Mais l'origine principale de l'erreur n'est pas dans le calcul, elle est dans la conversion de 2050.1, 2048.1, 4.1 et 2.1 en flottant qui a chaque fois introduisent une erreur relative de DBL_EPSILON.

    Les calculs elementaires eux-memes peuvent introduire des arrondis, quand le resultat exact n'est pas representable -- et la la borne est de DBL_EPSILON multiplie par le resultat (et on peut choisir la direction d'arrondi).

    Pour les calculs plus compliques -- par exemple les fonctions transcendantes comme sin -- la norme n'exige en pratique rien et l'erreur peut bien plus grande qu'une erreur relative de DBL_EPSILON. Ca va dependre de la qualite de l'implementation.

    Donc avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double x = 2048.1, y1 = 2050.1, y2 = x+2.0, z = 2.1, t1 = 4.1, t2 = z+2.0;
    On a abs(y1-x-2.0) qui peut valoir jusqu'a 2050*DBL_EPSILON et abs(t1-z-2.0) qui peut valoir jusqu'a 4*DBL_EPSILON.

    y2-x qui vaut exactement t2-z qui vaut exactement 2.0.

    Et d'ailleurs la question n'était pas par rapport aux entiers, mais aux flottants, ce dont on vient de parler pendant le thread.
    Telle que je l'ai comprise, la question portait explicitement sur des calculs entre entiers representes en flottant.

  11. #11
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet
    Premierement, ....
    OK là dessus on est d'accord

    C'est juste qu'il est simplement extrêmement dangereux ( et 99,99999% du temps faux) de penser que faire

    marchera....

  12. #12
    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 souviron34
    C'est juste qu'il est simplement extrêmement dangereux ( et 99,99999% du temps faux)
    Non. Je n'ai pas ecrit tant de comparaison en flottant que ca et j'en ai deja ecrit ou l'egalite etait la chose a faire

    Utiliser
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (fabs(x-2.0) < DBL_EPSILON)
    comme tu le conseillais plus haut est plus dangereux: l'effet est exactement le meme et mais la forme donne l'impression qu'on a regle le probleme.

    Les flottants c'est delicat a maitriser. Croire que deux ou trois petits trucs comme ne pas faire de comparaisons c'est suffisant est peut-etre encore plus dangereux que croire qu'ils se comportent comme des reels. Dans le second cas, on voit vite qu'il y a des problemes, dans le second on masque les plus visibles mais on ne les resoud pas reellement.

  13. #13
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    En fait, ya plus ou moins le meme probleme avec le paramètre de ceil et floor.. est-ce que ceil(6.0 / 2.0) va evaluer ceil(3.0001) ou ceil (2.9999)?

  14. #14
    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 Gruik
    En fait, ya plus ou moins le meme probleme avec le paramètre de ceil et floor.. est-ce que ceil(6.0 / 2.0) va evaluer ceil(3.0001) ou ceil (2.9999)?
    6 et 2 sont des entiers, donc representables exactement. Leur quotient est un entier, donc representable exactement. Les implementations actuelles des flottants donne le resultat exact quand il est representable, on a donc ceil(3.0000).

    Si tu poses la question avec ceil(6.6/2.2), ca va dependre car ni 6.6 ni 2.2 sont representables exactement.

  15. #15
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    Il me semblait que 0 n'était pas "representable exactement", je pensais que c'était pareil pour tous les entiers

  16. #16
    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 Gruik
    Il me semblait que 0 n'était pas "representable exactement", je pensais que c'était pareil pour tous les entiers
    0.0 est representable exactement. Mais il a deux representations: +0.0 et -0.0 ce qui fait quelques surprises. Par exemple 0.0-x pour x = 0.0 vaut +0.0, -x pour x = 0.0 vaut -0.0. Mais +0.0 == -0.0 donc la difference ne s'observe que difficilement.

  17. #17
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    D'accord

    Du coup, on peut tester "x == 3" si x vaut 3.0 ?

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

Discussions similaires

  1. Petite question sur les performances de Postgres ...
    Par cb44 dans le forum PostgreSQL
    Réponses: 5
    Dernier message: 13/01/2004, 13h49
  2. question sur les vertex buffer et index buffer
    Par airseb dans le forum DirectX
    Réponses: 9
    Dernier message: 25/08/2003, 02h38
  3. question sur les variables globales et les thread posix
    Par souris_sonic dans le forum POSIX
    Réponses: 5
    Dernier message: 13/06/2003, 13h59
  4. Question sur les handles et les couleurs...
    Par MrDuChnok dans le forum C++Builder
    Réponses: 7
    Dernier message: 29/10/2002, 08h45
  5. question sur les message box !
    Par krown dans le forum Langage
    Réponses: 7
    Dernier message: 02/08/2002, 16h11

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