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 :

[C# 2.0] Calculs inexplicablement imprécis


Sujet :

C#

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut [C# 2.0] Calculs inexplicablement imprécis
    Hello,

    J'ai un tableau de 5 flottants SCT[] que je veux additionner dans une variable x :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    SCT[0] = 1.8;
    SCT[1] = 2.0;
    SCT[2] = 0.0
    SCT[3] = 0.O;
    SCT[4] = 2.2;
     
    float x = 0.0F;
    for (int i = 0; i < 5; i++)
        x += SCT[i];
    Au déboguage, lors du rpemier passage dans la boucle, j'ai x= 1.8. Mais lors de la seconde, j'ai x = 4.39999962....

    Quelqu'un aurait-il une explication ? Merci.

  2. #2
    Invité
    Invité(e)
    Par défaut
    c'est normal les calculs sur les flottants sont toujours imprecis cela est du au mode de calcul des processeurs.

  3. #3
    Membre Expert
    Avatar de Mehdi Feki
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 113
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 113
    Par défaut
    Citation Envoyé par gcorbineau
    c'est normal les calculs sur les flottants sont toujours imprecis cela est du au mode de calcul des processeurs.
    Non ce n'est pas normal dans son cas

    Tu peux poster ton code d'origine parce que comme il est la, il ne devrait pas compiler

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Par défaut
    Même si les calculs en flottant sont non précis, rien n'explique un tel écart, le résultat théorique devrait être 3.8 or 4 et des cacahuetes c'est réellement anormal.
    En effet, sur des calculs aussi basiques, et des valeurs aussi simples, même des flottants simple précision sont largement suffisants, et on devrait dès lors obtenir des résultats cohérents.
    Je suis du meme avis que mehdi_tn, il nous faudrait le code complet pour mieux comprendre. Car là sans avoir clairement alloué SCT ca ne doit pas compiler.

  5. #5
    mow
    mow est déconnecté
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    210
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 210
    Par défaut
    C bizarre dans le code que tu proposes SCT[3] ne peut pas être un flottant.

    Mow

  6. #6
    Membre Expert
    Avatar de Mehdi Feki
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 113
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 113
    Par défaut
    Citation Envoyé par cinemania
    Car là sans avoir clairement alloué SCT ca ne doit pas compiler.
    entre autres, mais je faisais plutot reference aux affectations SCT[0] = 1.8;, qui doivent etre ecrites comme ca : SCT[0] = 1.8F;

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    En fait, ce n'est pas vraiment initialisé comme ça.

    Voici le code complet :

    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
    private void btnCalculs_Click(object sender, EventArgs e)
    {
        string profil = lstProfils[cbProfileECT.SelectedIndex].cle;
        string lettre_profil;
        lettre_profil = profil.Substring(0, 1);
     
        Program.coeffs.chargerTable("SELECT * FROM Alpha_Compression", "Alpha");
     
        float[] SCT = new float[5];
        SCT[0] = Single.Parse(tbSCT1.Text);
        SCT[1] = Single.Parse(tbSCT2.Text) * (float)Program.coeffs.extraireValeur("Select Alpha FROM Alpha_Compression WHERE Lettre='" + lettre_profil + "'");
        SCT[4] = Single.Parse(tbSCT5.Text);
     
        try
        {
            lettre_profil = profil.Substring(1, 1);
            SCT[2] = Single.Parse(tbSCT3.Text);
            SCT[3] = Single.Parse(tbSCT4.Text)
                 * (float)Program.coeffs.extraireValeur("Select Alpha FROM Alpha_Compression WHERE Lettre='" + lettre_profil + "'");
        }
        catch
        {
        }
     
        float x = 0.0F;
        for (int i = 0; i < 5; i++)
            x += SCT[i];
       ...
    }
    Le tableau SCT s'initialise tout seul à sa création avec la valeur flottante 0.0. Ensuite, je mets à jour SCT[0], SCT[1], et SCT[4]. Les tbSCT sont des chamsp textes contenant des valeurs avec comme séparateur décimal la virgule. Quand je débogue, après le Parse, j'ai bien les valeurs flottantes que j'avais données dans le premier message. Mais dans le for, il y a un soucis avec le calcul...

    Il y a un coefficient Alpha que je n'avais pas mentionné, mais j'étais en fait soucieux au sujet des nombreuses décimales.

    PS : avec le jeu de valeur avec lequel je fais ce test, je ne passe jamais dans le try

  8. #8
    Membre Expert
    Avatar de Mehdi Feki
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 113
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 113
    Par défaut
    Citation Envoyé par oodini
    PS : avec le jeu de valeur avec lequel je fais ce test, je ne passe jamais dans le try
    Tu n'as pas une exception levé par hasard avant le try ? Tu n'as pas recu de message ?

    Citation Envoyé par oodini
    PS : avec le jeu de valeur avec lequel je fais ce test, je ne passe jamais dans le try
    try
    {
    lettre_profil = profil.Substring(1, 1);
    SCT[2] = Single.Parse(tbSCT3.Text);
    SCT[3] = Single.Parse(tbSCT4.Text)
    * (float)Program.coeffs.extraireValeur("Select Alpha FROM Alpha_Compression WHERE Lettre='" + lettre_profil + "'");
    }
    catch
    {
    }
    Un catch Vide , les exceptions vont passés inapercues comme ca.

    Mes tout ton code dans un bloc try catch , recupere l'exception et affiche là.

  9. #9
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par mehdi_tn
    Tu n'as pas une exception levé par hasard avant le try ? Tu n'as pas recu de message ?
    Non.

    Citation Envoyé par mehdi_tn
    Un catch Vide , les exceptions vont passés inapercues comme ca.
    C'est fait exprès. Les cellules du tableau correspondent à 5 champs numériques. Ceux situés dans le try peuvent en pas être renseignés, et dans ce cas, je veux que les cellules du tableau restent à une valeur 0.0.

    Quant aux autres champs, le Parse marchera toujours, car je fais un contrôle de saisie en amont.

    Citation Envoyé par mehdi_tn
    Mes tout ton code dans un bloc try catch , recupere l'exception et affiche là.
    C'est une erreur de parsing, je la connais. :-)
    Là n'est pas le problème.

    Avant mon for, le contenu des cellules du tableau est exactement ce qu'il doit être. Mais quand je fais la somme, j'ai des calculs imprécis (pour info, alpha=1.3).

  10. #10
    Membre Expert
    Avatar de Mehdi Feki
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 113
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 113
    Par défaut
    Attends là ca se complique. Tu n'as pas d'exceptions mais tu ne passe jamais dans le try !!! Si tu commencais deja à resoudre ce probleme et voir pourquoi.

    Sais-tu utiliser le debugger ?

    Si tu faisais un breakpoint dans la boucle for, et tu supervise les valeur de ton tableau SCT et ta variable x. Peux tu nous soumettre dans ce cas une trace de la boucle For ?

  11. #11
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Tu me demandais si j'avais une exception avant le try, et je répond non.

    POur la suite, je m'étais mal exprimé. Je voulais dire par "je ne passe jamais dans le try", je voulais dire "le try n'est jamais parcouru (avec un jeu de valeur précis) sans provoquer avant la fin du bloc une exception.

    Donc, je rentre dans le try, et je lève une exception, que je ne traite pas.

    Pour le déboguage , avec le jeu de valeurs

    SCT[0] = 1.8;
    SCT[1] = 2.6;
    SCT[2] = 0.0
    SCT[3] = 0.O;
    SCT[4] = 2.2;

    Parcours de la boucle for :
    i=0 -> x = 1.8;
    i=1 -> x = 4.39999962;
    i=2 -> x = 4.39999962;
    i=3 -> x = 4.39999962;
    i=4 -> x = 6.59999943;

  12. #12
    Membre Expert
    Avatar de Mehdi Feki
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 113
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 113
    Par défaut
    Salut oodini,

    En fait, tu nous as mis dans une mauvaise piste dés le début, regarde le jeu de test de ton premier post

    Citation Envoyé par oodini
    SCT[0] = 1.8;
    SCT[1] = 2.0;
    SCT[2] = 0.0
    SCT[3] = 0.O;
    SCT[4] = 2.2;
    C'est un probleme de precision, utilise plutot un double qui resoudra partiellement ton probleme.

  13. #13
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Désolé, mais j'étais tellement focalisé sur le nombre de décimales que je n'ai pas fait gaffe au reste...

  14. #14
    Membre Expert
    Avatar de Mehdi Feki
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 113
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 113
    Par défaut
    Citation Envoyé par oodini
    Désolé, mais j'étais tellement focalisé sur le nombre de décimales que je n'ai pas fait gaffe au reste...
    C'est pas grave, mais est-ce que tu as résolu ton probleme au moins ?

  15. #15
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Pas vraiment.

    J'ai tout changé en double :

    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
    double[] SCT = new double[5];
     
    tbSCT1.Text = Single.Parse(tbSCT1.Text).ToString("0.00");
    tbSCT2.Text = Single.Parse(tbSCT2.Text).ToString("0.00");
    tbSCT3.Text = Single.Parse(tbSCT3.Text).ToString("0.00");
    tbSCT4.Text = Single.Parse(tbSCT4.Text).ToString("0.00");
    tbSCT5.Text = Single.Parse(tbSCT5.Text).ToString("0.00");
     
    SCT[0] = Double.Parse(tbSCT1.Text);
    SCT[1] = Double.Parse(tbSCT2.Text) * 1.3;
    // SCT[1] = Double.Parse(tbSCT2.Text) * (Double)AlphaHelper.getAlpha(lettre_profil);
    SCT[4] = Double.Parse(tbSCT5.Text);
     
    try
    {
        lettre_profil = cle.Substring(1, 1);
        SCT[2] = Double.Parse(tbSCT3.Text);
        SCT[3] = Double.Parse(tbSCT4.Text)
             * (float)AlphaHelper.getAlpha(lettre_profil);
    }
    catch
    {
    }
     
     
    double x = 0.0;
    for (int i = 0; i < 5; i++)
    {
        x += SCT[i];
    }
    Le problème survient plus tard (lors de l'ajout du dernier membre du tableau), mais survient toujours...

  16. #16
    Membre Expert
    Avatar de Mehdi Feki
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 113
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 113
    Par défaut
    Comme il est deja mentionné, il y a toujours des erreurs de precision en travaillant avec les valeurs pointées.

    Si tu initialise ton tableau directement avec les memes valeurs, est ce que le probleme persiste ?

    Et si tu recupere directement les valeurs à partir des textbox sans passer par les Single.Parse(tbSCT1.Text).ToString("0.00"); ?

  17. #17
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par mehdi_tn
    Comme il est deja mentionné, il y a toujours des erreurs de precision en travaillant avec les valeurs pointées.
    Je viens de relire, et je n'ai pas vu cette information.
    Jamais rien vu sur le sujet. Ca vient d'où ?

    Citation Envoyé par mehdi_tn
    Si tu initialise ton tableau directement avec les memes valeurs, est ce que le probleme persiste ?
    Si je fais une init juste avant le for, je n'ai plus le problème.
    Pourtant, ce sont toujours des valeurs pointées (tableau), et les valeurs dans le tableau sont exactement les mêmes que quand le tableau est initialisé par les Parse.

    Citation Envoyé par mehdi_tn
    Et si tu recupere directement les valeurs à partir des textbox sans passer par les Single.Parse(tbSCT1.Text).ToString("0.00"); ?
    Ce bloc de code ne sert pas au calcul. Il sert juste à formater ce qui a été entré.
    De toute façon, en le supprimant, ça ne change rien.

    Très bizarre...

  18. #18
    Membre Expert
    Avatar de Mehdi Feki
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 113
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 113

  19. #19
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Apparemment quelqu'un qui a comme moi beaucoup de questionnements, mais guère de réponses. :-)

  20. #20
    Inactif  
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Janvier 2007
    Messages
    6 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Par défaut
    Un détail sans doute, mais il me semble que une instruction du type :

    float [] x = new float[10]

    n'initialise pas obligatoirement les membres du tableau à 0 si x est local à une méthode.

Discussions similaires

  1. code imprécis calcul TVA
    Par nebil dans le forum Général JavaScript
    Réponses: 12
    Dernier message: 06/01/2012, 18h57
  2. [TP7] Calculer sin, cos, tan, sqrt via le FPU
    Par zdra dans le forum Assembleur
    Réponses: 8
    Dernier message: 25/11/2002, 04h09
  3. Calcul des numéros de semaine d'un calendrier
    Par Invité dans le forum Algorithmes et structures de données
    Réponses: 4
    Dernier message: 06/11/2002, 21h29
  4. Récupérer 10 nb différents avec un calcul aléatoire
    Par BXDSPORT dans le forum Langage
    Réponses: 3
    Dernier message: 04/08/2002, 02h35
  5. Algo de calcul de FFT
    Par djlex03 dans le forum Traitement du signal
    Réponses: 15
    Dernier message: 02/08/2002, 17h45

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