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 :

2 valeurs identiques, 2 test d'égalités identiques, 2 résultats différents ?


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 30
    Points : 25
    Points
    25
    Par défaut [RESOLU] 2 valeurs identiques, 2 test d'égalités identiques, 2 résultats différents ?
    Bonjour à tous,


    bon j'ai un problème qui me tarode. En codant, je suis resté bloqué un long moment sur une égalité qui ne produisait pas le résultat attendue, et j'ai remarqué qu'en réécrivant cette même égalité exactement de la même manière, hors de ma boucle (valeurs absolument identiques), cela produisait un résultat différent.
    Je peux donc résoudre mon problème facilement, mais je voudrais comprendre pourquoi le résultat est différent ?

    Voilà mon code :
    ***Version 1
    Dans cette version, on NE RENTRE PAS dans la boucle selon l'ordi la condition du for est FAUSSE (en fait elle est vraie si on vérifie de tête).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int i = 0;
    int step = 0;
    for(; (float)(powf(10.0f, -1.0f*((float)step+1.0f))*((float)i+1.0f))>=0.1f ; step++);
    Output : step = 0;

    ***Version 2
    Dans cette version, on RENTRE dans la boucle selon l'ordi la condition de boucle est VRAIE.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int i = 0;
    int step = 0;
    float conditionValeur = (float)(powf(10.0f, -1.0f*((float)step+1.0f))*((float)i+1.0f));
    for(; conditionValeur>=0.1f ; step++)
    {
       //réévaluation de "conditionValeur"
    }
    Output : step = 1;


    Je comprends pas du tout pourquoi.


    Quelqu'un aurait une idée ???


    Bonne soirée à tous.

  2. #2
    Membre averti Avatar de Kujara
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    262
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 262
    Points : 358
    Points
    358
    Par défaut
    A l'oeil :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int i = 0;
    int step = 0;
    for(; ((float)(powf(10.0f, -1.0f*((float)step+1.0f))*((float)i+1.0f)))>=0.1f ; step++);
    Essaye ça.

    Si ça marche, c'etait ton cast en float qui etait mal placé ....

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    267
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 267
    Points : 275
    Points
    275
    Par défaut
    Chez moi tout marche avec ton code...
    Juste une correction (mais de taille):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int i = 0;
    int step = 0;
    for(
      ;
      (float)(powf(10.0f, -1.0f*((float)step+1.0f))*((float)i+1.0f))>=0.1f ; 
      step++
    ) //;
    Pas de ; après le for.

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 30
    Points : 25
    Points
    25
    Par défaut
    Re.


    merci de vos idées. Mais c'est pas ça.

    Pour la réécriture que tu propose Kujara, c'est pareil que ce que j'ai écrit.
    J'ai écrit : ((float)(X)) et tu me dis d'écrire : (float)(X).
    En fait j'avais mit une parenthèse englobante en trop. Mais bon avec toutes ces parenthèses on s'y perd.
    (J'ai quand même testé ton code en copiant collant, et effectivement y a le même pb que sur le mien).

    Et sinon Albenejean, si si le ";" est volontaire car je n'ai pas de scope {} dans mon for. Donc c'est un for qui se débrouille tout seul comme un grand :-)
    Par contre je comprends pas que mon code marche chez toi. En même temps vaut mieux que le pb ne soit que sur mon ordi.

    Au passage : je bosse sous Visual .NET 2003 et Win XP Pro.



    Quelqu'un a une autre idée ?

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    267
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 267
    Points : 275
    Points
    275
    Par défaut
    OK je viens de comprendre ce que tu ne comprends pas (ou du moins je crois avoir compris)........

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    using namespace std;
     
    int main()
    {
        {
            int i = 0;
            int step = 0;
            cout<<"Test = "<<((float)(powf(10.0f, -1.0f*((float)step+1.0f))*((float)i+1.0f))>=0.1f )<<"\n";
            for(; (float)(powf(10.0f, -1.0f*((float)step+1.0f))*((float)i+1.0f))>=0.1f ; step++);
            cout<<"step = "<<step<<"\n";
        }
        cout<<"----\n";
        {
            int i = 0;
            int step = 0;
            float conditionValeur = (float)(powf(10.0f, -1.0f*((float)step+1.0f))*((float)i+1.0f));
            cout<<"Test = "<<(conditionValeur>=0.1f)<<"\n";
            for(; conditionValeur>=0.1f ; step++)
            {
                conditionValeur = (float)(powf(10.0f, -1.0f*((float)step+1.0f))*((float)i+1.0f));
            }
            cout<<"step = "<<step<<"\n";
        }
    }
    Donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Test = 1
    step = 1
    ----
    Test = 1
    step = 2
     
    Process returned 0 (0x0)   execution time : 0.015 s
    Press any key to continue.
    Comme tu peux le voir, tes 2 test sont identiques. Par contre
    Si par
    //réévaluation de "conditionValeur"
    tu recalcule simplement conditionValeur, step ne sera pas augmenter lors du premier passage dans la boucle.

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 30
    Points : 25
    Points
    25
    Par défaut
    En fait pour être plus précis la méthode 2 je ne l'ai testé que parce que je ne comprenais pas pourquoi la 1 ne fonctionnait pas.
    Mais quand je test la méthode 2 je fais la réévaluation de la valeur avec step+1. Je l'ai pas précisé, pour pas encombrer.

    Donc pour être plus exacte voilà la méthode 2 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int i = 0;
    int step = 0;
    
    float conditionValeur = (float)(powf(10.0f, -1.0f*((float)step+1.0f))*((float)i+1.0f));
    for(; conditionValeur>=0.1f ; step++)
        conditionValeur = (float)(powf(10.0f, -1.0f*((float)(step+1)+1.0f))*((float)i+1.0f));

    Par contre, je vais tester ton code sur mon ordi, on sait jamais...

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 30
    Points : 25
    Points
    25
    Par défaut
    Je crois que j'ai trouvé : C++ se paie ma tête.

    En prenant ton code copié, collé, ça fonctionne dans un nouveau programme. Mais quand je le copie colle dans mon programme, ça créé toujours le même problème.

    Je n'ai pas changé un caractère. Je comprends pas du tout.


    Voilà exactement ce que je tape dans mon progr (MFC) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int i = 0;
    int step = 0;
    for(; (float)(powf(10.0f, -1.0f*((float)step+1.0f))*((float)i+1.0f))>=0.1f ; step++);
     
    char msg[10];
    sprintf(msg, "step = %i", step);
    CWnd::GetActiveWindow()->MessageBox(msg);
    Output : step = 0

    Bref, je ne comprends pas plus.
    Au fait merci Albenejean de tes conseils.

  8. #8
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    267
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 267
    Points : 275
    Points
    275
    Par défaut
    Note que je viens de tester mon code (avec le bon calcul de conditionValeur) avec VC++ 2003 Toolkit et VC 2005 Express et les résulats de mon code sont biens différents:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    VC++ 2003
     
    Test = 0
    step = 0
    ----
    Test = 0
    step = 1
     
    Process returned 0 (0x0)   execution time : 0.015 s
    Press any key to continue.
     
     
    -----------------
    VC++ 2005
     
    Test = 1
    step = 1
    ----
    Test = 1
    step = 1
     
    Process returned 0 (0x0)   execution time : 0.015 s
    Press any key to continue.
    Donc avec ce vieux compilo qu'est (étaient) VC++ 2003, le test est faux...
    Bref change de compilo!

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 30
    Points : 25
    Points
    25
    Par défaut
    Merci Albenejean pour tous tes tests. C'est super sympa de passer autant de temps pour aider les autres.

    En plus c'est cool maintenant je sais d'où ça vient. La curiosité me rongeait.


    Mais c'est un coup dur pour moi que d'apprendre que mon compilateur est "vieux". J'ai même du mal à le dire.
    Mais bon je peux pas changer tout de suite, j'ai une version légale et je suis pas du genre à prendre une version illégale. Oh que non. (attention à ce que l'on dit sur internet, avec toute cette surveillance on est plus en sécurité nul part, hehe).

    Merci encore pour ton aide.

  10. #10
    Membre actif
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    267
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 267
    Points : 275
    Points
    275
    Par défaut
    Note que Visual C++ 2005 Express est disponible en version légale.

    Note aussi qu'en ajoutant l'option de compilation sur la précision des float (/Op), on obtient le résultat correct avec VC++2003.

    Mais bon, je te conseille de passer à une version plus récente.

  11. #11
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Points : 1 543
    Points
    1 543
    Par défaut
    Salut,

    Et bienvenue dans le monde merveilleux des calculs sur les nombres flottants...

    Déjà voilà quelque chose qui explique que l'égalité peut effectivement être fausse même si elle est juste (si si !) : http://support.microsoft.com/kb/125056/EN-US
    En fait il peut tout à fait y avoir des différences d'un compilateur à l'autre, et même des différences d'une option de compilation à l'autre (en l'occurence entre debug et release), et apparemment encore plus si affinité.

    La bonne méthode quand on manipule des nombres flottants c'est de tester que la valeur ne s'éloigne pas de la valeur attendue d'un certain epsilon, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::abs( expectedValue - actualValue ) < std::numeric_limits< float >::epsilon()
    MAT.

  12. #12
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Points : 1 543
    Points
    1 543
    Par défaut
    Enfin donc pour ton cas là pour résoudre le problème tu peux faire quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    static const float epsilon = 0.001f;
    for(; (float)(powf(10.0f, -1.0f*((float)step+1.0f))*((float)i+1.0f))>=0.1f - epsilon ; step++);
    En ajustant éventuellement epsilon suivant l'ordre de grandeur du résultat attendu.

    MAT.

Discussions similaires

  1. Mongo : test deux champs identiques
    Par Cibou dans le forum Doctrine2
    Réponses: 3
    Dernier message: 19/12/2014, 11h36
  2. Réponses: 4
    Dernier message: 08/05/2012, 10h58
  3. [PHP 5.2] Additionner les valeurs de 2 tableaux si clés identiques
    Par renaud26 dans le forum Langage
    Réponses: 3
    Dernier message: 23/04/2011, 19h41
  4. Test d'égalité des valeurs
    Par matt41fr dans le forum Mathématiques
    Réponses: 11
    Dernier message: 12/03/2009, 13h13
  5. Réponses: 5
    Dernier message: 04/01/2006, 19h34

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