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 :

précision de l'incrément dans boucle for


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2014
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 57
    Par défaut précision de l'incrément dans boucle for
    bonjour,


    voici le début de ma boucle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    for (double g = gmin; g <= gmax; g += 0.1)
    les valeurs de gmin et gmax par défaut étaient de -2.1 et -1.9, tout allait dans mon code sauf quand j'ai augmenté l'écart entre gmin et gmax (respcitivement -2.5 et -1.7 soit 9 possibilités)
    après avoir pas mal cherché où ça pouvait merder, il s'est avéré que ça vient de la valeur de g dans ma boucle voici les valeurs que j'ai aux différentes itérations
    1 : -2.5
    2 : -2.4
    3 : -2.3
    4 : -2.19999997
    5 : -2.09999996
    6 : -1.99999996
    7 : -1.88888885
    8 : -1.79999994
    et l'itération 9 est zapée du coup
    j'ai essayé de mettre "1/10" a la place de 0.1 au niveau de l'incrément, mais ça fonctionne pas
    la parade que j'ai trouvé c'est de mettre en borne sup "gmax+0.001"
    mais j'aimerais bien comprendre pourquoi il y a un décalage qui se fait et comment l’empêcher sans bricolage.

    merci

  2. #2
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Billets dans le blog
    3
    Par défaut
    C'est lié au type double, qui n'est pas aussi précis qu'on pourrait le penser. Cela est en partie dû à la représentation binaire des chiffres à virgule flottante... Il y a pas mal d'explications ici : Using “double” as counter variables in loops.

    Notamment celle-ci :
    And. The traditional replacement for a == b for floats is abs(a-b) < epsilon where epsilon is less then expected precision. For example, epsilon = 0.001 if all the used numbers are not more precise than 0.01.
    Petite traduction pour les non anglophones :
    L'égalité a == b pour les floats est traditionnellement remplacée par abs(a - b) < epsilon, où epsilon est inférieur à la précision attendue. Par exemple, epsilon = 0.001 si tous les nombres utilisés ne sont pas plus précis que 0.01.
    Donc le meilleur moyen de parer à cela est de définir une tolérance acceptable pour ton égalité, et de mettre cette valeur à la place d'epsilon (0.0001 dans l'exemple ci-dessous) :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    for (double g = gmin; Math.Abs(gmax - g) < 0.0001; g += 0.1)
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  3. #3
    Membre chevronné Avatar de pascalCH
    Homme Profil pro
    Formateur en informatique
    Inscrit en
    Juillet 2006
    Messages
    188
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Formateur en informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juillet 2006
    Messages : 188
    Par défaut
    Il s'agit bien d'un problème récurrent lié aux unités arithmétiques et aux générateurs de code des compilateurs.
    Un test intéressant est de comparer les résultats entre une exécution suite à une compilation en mode "Debug" et le même code compilé en mode "Release"...

    Sinon, une façon de contourner - peut être - le problème : Mettre les points sur les "i" au compilateur en mettant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Double gmin = (-2.5D);
    Double gmax = (-1.7D);
    // ....
    for ( Double g = (Double)gmin ; g < (Double)gmax ; g = (Double)( g + 0.1D) )
    Ça donne l'impression de prendre le compilateur pour un demeuré, mais au moins ça ne déclenche pas des conversions Double <-> Single indésirables.

  4. #4
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    DotNetMatt a fourni la bonne réponse: certains nombres ayant peu de chiffres après la virgule en décimal en ont beaucoup en binaire, davantage que ce qui est disponible.

    Le passage à un pas de 0.01 laissera toujours des cas problématiques. Tout comme à mon avis (à vérifier) la solution de pascalCH. Les deux bonnes solutions sont :
    * Utiliser un entier dix fois plus grand et bricoler (le convertir là où c'est possible, garder un entier pour les autres cas).
    * Utiliser un type "decimal" qui est représenté en décimal et non en binaire.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2014
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 57
    Par défaut
    merci pour vos réponses, maintenant je comprends le pourquoi du comment

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

Discussions similaires

  1. Réponses: 9
    Dernier message: 15/09/2006, 20h08
  2. [débutant] Pb dans boucle For
    Par Sam 069 dans le forum Access
    Réponses: 2
    Dernier message: 11/09/2006, 14h10
  3. Réponses: 3
    Dernier message: 04/08/2006, 20h24
  4. problème dans boucle for de lecture de fichier ini
    Par chourmo dans le forum Delphi
    Réponses: 3
    Dernier message: 06/07/2006, 10h31
  5. [JLabel] JLabel dans boucle for
    Par clairenes dans le forum AWT/Swing
    Réponses: 2
    Dernier message: 06/01/2006, 01h47

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