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 :

boucle for: indice double


Sujet :

C++

  1. #1
    Membre éclairé
    Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2010
    Messages
    382
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2010
    Messages : 382
    Par défaut boucle for: indice double
    Bonjour,

    Je veux afficher les valeurs entre 0 et 359.99, j'ai fait la boucle suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for (double i=0; i<360.; i+=0.01)
    				 {
    					 printf("%f\n", i);
    				 }
    mais j'ai la valeur 360 aussi affichée

    Qu'est ce qui ne va pas dans cette boucle?
    Merci d'avance

  2. #2
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    C'est du C, pas du C++

    Sinon, aucun souci en théorie.
    Par contre en pratique: bienvenue dans les problèmes de précision et des nombres flottants non représentables (comme 1/3 en décimal)

    Exécute ce programme pour mieux comprendre ce qu'il se passe.
    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
    // g++ -Wall -Wextra i_double.cpp -o i_double
     
    # include <iostream>
    # include <limits>
     
    int main()
    {
    	std::cout.precision(std::numeric_limits<double>::digits10+1);
     
    	for (double i = 0; i < 360.; i += 0.01)
    	{
    		std::cout << i << std::endl;
    	}
     
    	for (int i = 0; i < 360 * 100; ++i)
    	{
    		std::cout << double(i) / 100 << std::endl;
    	}
    }
    Le deuxième boucle devrait faire ce que tu veux.

  3. #3
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    En gros, 0.01 + 0.01 + 0.01 + (...) + 0.01 +0.01 (répété 36000 fois) est différent de 360.0
    A lire : Les nombres flottants et leurs pièges ainsi que les autres articles de la série (non encore traduit)

  4. #4
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Avec les erreurs d'arrondi, je parie que tu te retrouves avec un 359.9999999999 qui est inférieur à 360, mais s'affiche comme tel dans le printf().
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre éclairé
    Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2010
    Messages
    382
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2010
    Messages : 382
    Par défaut
    Merci tout le monde
    effectivement Médinoc, c'est ce que j'ai trouvé lorsque j'ai exécuté pas à pas

  6. #6
    Membre éclairé
    Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2010
    Messages
    382
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2010
    Messages : 382
    Par défaut
    Salut, j'ai trouvé le même problème lors de l’écriture dans le fichier

    j'ai une valeur de 2,59045392, mais la valeur affichée dans le fichier est 2,59; sachant que le cumul de ces erreurs me donne un mauvais résultat à la fin de mes calculs

    j'utilise ce bout de code pour l'ecrture
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ofstream fichier2("validation2.csv", ios::out | ios::trunc);  // ouverture en écriture avec effacement du fichier ouvert
    					if(fichier2)
    					{
    						for (int i=0; i<vect.size(); i++)
    						{
    							fichier2 << vect.at(i) << endl;
    						}
    						fichier2.close();
    					}
    comment je peux résoudre le problème d'affichage
    merci d'avance

  7. #7
    Membre émérite
    Avatar de Daïmanu
    Homme Profil pro
    Développeur touche à tout
    Inscrit en
    Janvier 2011
    Messages
    735
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur touche à tout

    Informations forums :
    Inscription : Janvier 2011
    Messages : 735
    Par défaut
    Si ton vecteur contient des doubles, tu peux jouer avec les manipulateurs d' <iomanip>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    for (size_t i=0; i<vect.size(); i++)
    {
        //Demande d’afficher 8 chiffres après la virgule
        fichier2 << std::fixed << std::setprecision(8) << vect.at(i) << std::endl;
    }

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    Ne serait-il pas plus intéressant de travailler en virgule fixe ?

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    Je te conseille d'éviter le plus possible de travailler avec des décimaux.
    Préfère utiliser des entiers, puis quelques divisions pour atteindre ton résultat.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  10. #10
    Membre Expert
    Inscrit en
    Août 2010
    Messages
    732
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 732
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Bonjour,

    Je te conseille d'éviter le plus possible de travailler avec des décimaux.
    Préfère utiliser des entiers, puis quelques divisions pour atteindre ton résultat.
    Justement, si c'était des décimaux son code fonctionnerait. C'est des binaires.

  11. #11
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Citation Envoyé par Hibernatus34 Voir le message
    Justement, si c'était des décimaux son code fonctionnerait. C'est des binaires.
    pas compris
    Bousk parle de ne pas utiliser des nombres décimaux (nombres à virgule flottant), mais des entiers (3DArchi a fait la même remarque)
    Tu appelles quoi "des binaires" ?

  12. #12
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Hibernatus dit que si c'étaient des décimaux (nombre à virgule flottante en décimal) ça marcherait, mais que malheureusement il s'agit ici de nombres à virgule flottante en binaire.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  13. #13
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Ah ok, j'avais pas compris (à force de faire des raccourcis )

  14. #14
    Membre Expert
    Inscrit en
    Août 2010
    Messages
    732
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 732
    Par défaut
    Oui, c'est bien ce que je voulais dire.
    Quand on a compris qu'il s'agit de binaire (2^3 + 2^0 + 2^-1 + 2^-5...) on a tout compris.

  15. #15
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Juste pour chipoter, la limite vient du fait que c'est une approximation avec une nombre limité de digits, pas de la représentation binaire en elle même (on peut écrire pi en binaire avec une infinité de bits je crois, à confirmer par un vrai matheux)

  16. #16
    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 gbdivers Voir le message
    Juste pour chipoter, la limite vient du fait que c'est une approximation avec une nombre limité de digits, pas de la représentation binaire en elle même (on peut écrire pi en binaire avec une infinité de bits je crois, à confirmer par un vrai matheux)
    Oui (pour pi)

    Il y a deux choses. Premieremement, un nombre fini de bits signifie qu'on n'a qu'un nombre fini de nombres quelque soit la representation. Donc pour les reels on se retrouve limite en intervalle (il y a un plus grand et plus petit reel representable -- les flottants ont parfois une representation pour l'infini, mais ces infinis ne sont plus des reels) et en precision (entre deux reels, il y en a une infinite de reels, entre deux flottants, il y a un nombre fini eventuellement nul de flottants).

    Une representation binaire se retrouve a ne pas pouvoir representer des nombres qui ont une representation simple en decimal (comme 0.1). Si on se contente de lire et de reecrire des nombres avec une addition ou deux, une representation decimale a moins de probleme parce qu'elle partage les limitations du format d'entree. Si on fait un peu plus de calculs, la precision finie va etre limitante avec l'un et l'autre. Et le format decimal offre aussi des surprises que le format binaire n'a pas (p.e. (a+b)/2 peut etre plus grand que a et que b alors que le resultat exact est representable, bon amusement si tu fais une recherche par dichotomie).

    En resume, la precision est meilleure avec les flottants binaires mais il y a des cas ou les decimaux donnent une solution exacte et pas les binaires. Ces cas importe peu en pratique, il y aura toujours des resultats inexacts. Dans les cas, comme en comptabilite, ou on est contraint par des regles d'arrondi specifiee en decimal, les flottants decimaux n'aident a ma connaissance pas: ces regles sont specifiees pour des representations en virgule fixe, pas pour des representations flottantes et si on se met a utiliser les flottants decimaux en profitant que ce sont des flottants, c'est fichu. Et meme dans cette zone, il y a des risques de double arrondi, donc il faut se taper exactement la meme analyse de precision qu'avec des flottants binaires -- l'implementation pouvant etre legerement facilitee -- ou utiliser les flottants decimaux comme des entiers , ce qu'on peut faire avec les flottants binaires ou des long long -- a nouveau on peut avoir une implementation legerement facilitee, mais l'analyse est la meme.

  17. #17
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Je ne comprends pas ce que tu veux dire sur (a+b)/2...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  18. #18
    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 Médinoc Voir le message
    Je ne comprends pas ce que tu veux dire sur (a+b)/2...
    Avec des flottants ayant 3 chiffres significatifs.

    9.99E1 + 9.97E1 = 19.96E1 qu'on doit arrondir a 2.00E2

    2.00E2/2 = 1.00E2 alors que la moyenne est 9.98E1 et est representable.

  19. #19
    Membre Expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Par défaut
    eh bien change donc écris plutôt a/2 + b/2 ^^

  20. #20
    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 germinolegrand Voir le message
    eh bien change donc écris plutôt a/2 + b/2 ^^
    Tu arrives a 9.97E1 plutot que 9.98E1. C'est a + (b-a)/2 qu'il faudrait ecrire. Mais le point est qu'il faut faire attention des qu'on utilise des flottants, et que les flottants decimaux ne sont pas une solution qui permette d'eviter les analyses.

Discussions similaires

  1. doubles boucles for
    Par tpscience dans le forum MATLAB
    Réponses: 7
    Dernier message: 26/04/2009, 19h38
  2. Incrémentation d'un indice avec une boucle for
    Par Faladin dans le forum VB.NET
    Réponses: 3
    Dernier message: 12/05/2008, 14h56
  3. [batch] double boucle for
    Par schlopa dans le forum Windows
    Réponses: 12
    Dernier message: 11/02/2008, 19h54
  4. Sortir d'une double boucle FOR-END
    Par Invité dans le forum MATLAB
    Réponses: 4
    Dernier message: 05/12/2007, 11h07
  5. Action sur l'indice d'une boucle "FOR"
    Par Phelix2003 dans le forum MATLAB
    Réponses: 13
    Dernier message: 12/11/2007, 16h44

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