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

  1. #41
    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).

  2. #42
    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++

    +

  3. #43
    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.

  4. #44
    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
    @mujigka :

    je pense, mais je ne m'y fierais pas (tout dépend de l'implémentation je pense..

    Normalement, il doit y avoir une addition quelque part :

    floor == (double)((int)(x+0.5))

    Donc d'une part c'est le résultat d'un calcul, et ensuite il y a un double cast.
    il y a donc de bonnes chances que ça ... marche ?? marche pas ???

    Aucune idée....

  5. #45
    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.

  6. #46
    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....

  7. #47
    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 mujigka
    Oui, mais la quiestion de Gruik était:

    Dans le cas de ceil() et floor(), on est garantit d'obtenir une valeur entière représentable exactement, non?
    Par IEEE 754, oui. Si je ne me trompe pas, en C pur il n'y a de contraintes/recommandations sur la precision des calculs que pour la conversion des constantes (le flottant le plus proche ou un des deux autours) et strtod (soit un des flottants encadrant le nombre exact).

  8. #48
    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 Jean-Marc.Bourguet
    Par IEEE 754, oui. Si je ne me trompe pas, en C pur il n'y a de contraintes/recommandations sur la precision des calculs que pour la conversion des constantes (le flottant le plus proche ou un des deux autours) et strtod (soit un des flottants encadrant le nombre exact).
    Donc, de manière générale, si on désires écrire du code portable, sans faire de supposition sur la conformité des implantations considérées à la norme IEEE 754, dès qu'il y a des calculs, on ne peut supposer une représentation exacte du résultat. 2.0 * 3.0 == 6.0 ou floor(10.0/3.0) == 3.0 ne font pas exception, et cela rejoint ce que dit souviron34.

    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++

    +

  9. #49
    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.

  10. #50
    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/).

  11. #51
    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
    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.
    .
    D'accord là-dessus, c'était juste pour dire.

    Normalement c'est

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    if (fabs(x-2.0) < MA_PRECISION)

    Par contre, surtout ne pas utiliser :

    Si x est un flottant normal....

    Cela ne marchera quasi jamais... et de plus ça n'est pas recommandé, à cause de ça (voir mes 2 références plus haut, mais n'importe quel guide de programmation en C)..

    @mujigka : oui c'est bien ça la conclusion

  12. #52
    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 Ulmo
    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/).
    Le format étendu fait partie des formats definis par IEEE 754.

  13. #53
    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
    OK, j'avais mal interpreté le passage que je citais.

+ Répondre à la discussion
Cette discussion est résolue.
Page 3 sur 3 PremièrePremière 123

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