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 :

Mystérieux 1.#QNAN . . .


Sujet :

C

  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2013
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2013
    Messages : 21
    Par défaut Mystérieux 1.#QNAN . . .
    bonjour à tous je suis nouveau sur le forum et j'ai un petit soucis...
    j'ai codé une fonction qui doit me retourner la racine du nombre donné en argument. ça marche quasiment sauf le moment ou la fonction test retourne la variable:

    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
     
    float test(float min, float max, float nb)
    {
        float mid;
        float resultat;
     
        mid=(max+min)/2;
        resultat=mid*mid;
     
        printf("min:%.2f\t mid:%.2f\tmax:%.2f\n",min,mid,max);
        //system("pause");
     
        if(resultat<nb)
        min=mid;
        else if(resultat>nb)
        max=mid;
        else
        {
            printf("RESULTAT: %f\n",mid);
            return mid;
        }
     
     
        test(min,max,nb);
    }
     
    float racine(float nb)
    {
        if(nb==0)
        return 0;
        float max=nb;
        float min=0;
        float resultat = test(min,max,nb);
        printf("RESULTAT: %f\n",resultat);
        return resultat;
    }
     
    int main()
    {
        float nb=1;
        if(nb<0)
        {printf("nb est negatif!\n");
        exit(EXIT_FAILURE);}
     
        printf("la racine de %.2f est: %.2f",nb,racine(nb));
    }
    avec les printf j'obtiens:

    RESULTAT: 1.000000
    RESULTAT: 1.#QNAN0
    la racine de 1 est 1.#R

    Voila, je comprend pas comment le premier peut être correct et le second faux... si quelqu'un peut m'éclairer

    merci!

  2. #2
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Bonjour,

    bienvenu dans le monde des réels en informatique
    Dès que tu vois Nan cela signifie «Not A Number», ici le Q signifie Quiet.

    Plusieurs lectures s'imposent :
    IEEE754 et les réels en C
    Qu'est-ce qu'un Nan ?
    Comment comparer deux réels

    En gros l'erreur provient du fait que tu ne peux pas faire de la trichotomie sur les floats/double comme tu le fais (soit <, soit >, sinon ==), car tes calculs ensuite vont donner des nombres qui ne sont plus représentables correctement dans la norme utilisée.

  3. #3
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2013
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2013
    Messages : 21
    Par défaut
    ok, merci! maintenant j'ai mal à la tête mais au moins j'y vois plus clair!
    Je pourrais modifier mon code comme cela?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    #define EPSILON 0.0000001
    ...
    if(resultat-nb<EPSILON)
    //instructions

  4. #4
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Non
    Déjà il faudrait comparer la valeur absolue des différences, par exemple si resultat-nb vaut -1 le test est ok.
    Ensuite il est souvent plus robuste d'utiliser quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    if ( fabs(resultat-nb) < EPSILON*fabs(nb) ) {
      // ici resultat est suffisamment proche de nb pour pouvoir les considérer
      // comme étant égaux
    } else if (resultat<nb) {
      ...
    } else { /* ici resultat>nb */
      ...
    }
    Le premier if mesure en fait une égalité relative à l'ordre de grandeur de nb, et EPSILON mesure la tolérance à partir de laquelle on considère deux nombres suffisamment proches égaux. Mais attention ... nb ne doit pas être nul ...

  5. #5
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2013
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2013
    Messages : 21
    Par défaut
    ah d'accord!
    J'avais testé mon code et ça ne marchait pas, donc je venais de voir qu'il me fallait l'écart absolu entre la valeur calculée et la valeur réelle.
    Par contre d’où vient:

    EPSILON*fabs(nb)

    J'aurais juste mis EPSILON moi...
    D'autant plus que nb est forcément positif puisque c'est l'argument passé à la fonction?

    Du coup j'obtiens cette structure conditionnelle:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        if(fabs(resultat-nb) < EPSILON)
            return mid;
        else if(resultat>nb)
            max=mid;
        else
            min=mid;
        test(min,max,nb);
    Mais le probleme du #QNAN est toujours là... J'ai du rater un truc moi

  6. #6
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    On part du principe que les flottants a et b sont considérés comme égaux s'ils sont très proche l'un de l'autre. Une manière de faire est comme dans ton premier jet de comparer leur différence (mais en valeur absolue) : fabs(a-b) < EPSILON en se disant qu'avec un epsilon suffisamment petit ça se passera bien. Néanmoins comme les float n'ont que 7 ou 8 chiffres significatifs cela peut poser des problèmes si les valeurs comparées sont grandes et l'epsilon trop petit ...

    Du coup on préfère comparer leur rapport à 1, ce qui permet d'avoir un epsilon moins sensible à l'ordre de grandeur des nombres comparés |1-a/b|=|(a-b)/b|<epsilon, que l'on transforme en (pour éviter une division coûteuse) |a-b|<epsilon*|b| (enfin ça fonctionne si b est non nul).

  7. #7
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2013
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2013
    Messages : 21
    Par défaut
    all right!
    mais alors, malgré cela, le programme devrait fonctionner?
    Pourtant j'ai toujours ce #QNAN!
    Alors que lorsque j'affiche la valeur dans la fonction test() ça marche et pas dans la fonction racine.
    Comment est-ce possible ?

    édit1: je copie le code maintenant remodifié...
    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    #include <stdio.h>
    #include <stdlib.h>
    #define EPSILON 0.001
     
    float test(float min, float max, float nb)
    {
        float mid;
        float resultat;
     
        mid=(max+min)/2;
        resultat=mid*mid;
     
        if(fabs(resultat-nb) < EPSILON*fabs(nb))
            return mid;
        else if(resultat>nb)
            max=mid;
        else
            min=mid;
        test(min,max,nb);
    }
     
    float racine(float nb)
    {
        float max=nb;
        float min=0;
     
        if(nb<0)
        exit(EXIT_FAILURE);
     
        else if(nb==0)
        return 0;
     
        else
        return test(min,max,nb);
    }
     
    int main()
    {
        float nb=9.0;
        printf("la racine de %.2f est: %.2f",nb,racine(nb));
    }
    édit2: De toute façon n’exige t'il pas un epsilon machine que je pourrais utiliser dans mon cas?

    et encore merci pour ton aide

  8. #8
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Arrg ... j'ai laissé passer une erreur dans ton code !
    Ta fonction test est récursive ... tu as bien un return en cas d'égalité mais aucun pour les appels récursifs. En un mot, ton appel récursif ne devrait pas être test(min,max,nb); mais return test(min,max,nb);.
    Avec cette erreur la valeur renvoyée est indeterminée et dans ton cas renvoye un QNan ...

  9. #9
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2013
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2013
    Messages : 21
    Par défaut
    OMG toute cette puissance dans un seul homme!

    ca y est ça marche!

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

Discussions similaires

  1. Sortie de type Nan , QNaN
    Par phy4me dans le forum Fortran
    Réponses: 5
    Dernier message: 27/05/2007, 15h57
  2. parseint mystérieux !
    Par nox75 dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 21/05/2007, 17h17
  3. Probléme Mystérieux sur Fichier
    Par DonFelipe dans le forum Autres Logiciels
    Réponses: 2
    Dernier message: 26/01/2007, 21h02
  4. #QNAN et #IND
    Par koushkov dans le forum C++
    Réponses: 3
    Dernier message: 18/05/2006, 16h48
  5. Réponses: 6
    Dernier message: 16/03/2006, 12h17

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