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

SL & STL C++ Discussion :

Question sur les std::map


Sujet :

SL & STL C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 89
    Points : 57
    Points
    57
    Par défaut Question sur les std::map
    Bonjour à tous,

    J'ai fait une petite modification dans mon programme qui a généré un important temps de calcul.
    Pour simplifier, ceci est un programme contenant deux bouts de codes qui font la même chose :
    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
     
    double justePourVoir(std::map<double,double> mymap,int i)
    {
    	return mymap[i];
    }
    main()
    {
    clock_t aa,bb,cc;
    std::map<double,double> mymap;
    for(int i=0;i<500;i++)
    	mymap[i]=rand();
    double sum1=0,sum2=0;
    aa=clock();
    for(int i=0;i<500;i++)//1er bout de code
    	sum1+=mymap[i];
    bb=clock();
    for(int i=0;i<500;i++)//2eme bout de code
    	sum2+=justePourVoir(mymap,i);
    cc=clock();
    double t1=bb-aa;
    double t2=cc-bb;
    }
    Quand j'exécute, j'ai t1=0 et t2=8000 !
    Quelqu'un aurait une idée sur la source du problème?

    D'avance merci !

  2. #2
    Membre actif
    Étudiant
    Inscrit en
    Octobre 2007
    Messages
    189
    Détails du profil
    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2007
    Messages : 189
    Points : 214
    Points
    214
    Par défaut
    La copie inutile de la map car elle n'est ni passée par pointeur, ni par référence.

  3. #3
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    Effectivement, le passage par référence est nécessaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    double justePourVoir(const std::map<double,double> & mymap,int i)
    {
    	return mymap[i];
    }
    Plus d'infos ICI

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Salut,

    Pour commmencer, expliquons le fait que tes valeurs aléatoires soient identiques:

    Avant de vouloir générer une valeur aléatoire tu dois initialiser le générateur, généralement en lui passant la valeur time(NULL) pour qu'il prenne... l'heure système en compte dans son algorithme.

    Ensuite, la fonction rand (héritée du C, faut il le rappeler ) est un générateur aléatoire de... nombres entiers, dont la norme C garanti qu'il sera au minimum compris entre 0 et 32767.

    Et là, les problèmes commencent

    Il faut savoir qu'il n'est jamais bon de vouloir transformer "brut de force" un entier en réel, or c'est ce que tu fais.

    En effet, les réels ont la sale manie de souffrir d'une imprécision, au delà d'un certain point.

    La manière même dont les données sont représentées en mémoire est responsable de cette imprécision, et il existe, tant pour les double que pour les float, une valeur bien précise, nommé epsylon, en dessous de laquelle nous obtenons l'égalité étrange 1-epsylon == 1 == 1+ epsylon.

    Autrement dit, lorsque tu va essayer de transformer ton "1" entier en "1" réel, il pourrait tout aussi bien valoir 0.999999999 que... 1.000000001 (avec peut etre plus ou moins de chiffres derrière la virgule).

    Cette imprécision à elle seule justifie amplement le fait que l'on n'utilise que très rarement les réels pour représenter des clés de tri.

    De plus, la conversion de réel en entier à la manière "brut de force" pose également de sérieux problèmes:

    Par exemple, la conversion du réel 1.6 en entier donnera... 1, car la partie décimale est simplement perdue, alors que, selon les règles d'arrondi, cela aurait du donner... deux.

    Si tu avais "correctement" réglé ton compilateur (AKA avec l'option "Wconversion" sous Gcc), il aurait déjà pu t'avertir que
    |warning: conversion to 'int' from 'double' may alter its value|
    De plus, il faut savoir que l'opérateur [] d'une std::map n'agit pas du tout de la même manière que l'opérateur [] d'un std::vector ou d'un tableau "C Style"

    En effet, lorsque tu utilise un std::vector ou un tableau "C style", l'opérateur [] te permet d'accéder à l'élément dont l'indice est donné entre les crochets.

    Or, une std::map n'est pas un tableau: c'est un conteneur trié utilisant d'un coté une clé pour effectuer le tri et la recherche et de l'autre une valeur représentée par la clé (et, bien que le vocable "tableau associatif" soit courremment utilisé, il me gène quelque peu par la fausse idée que peut induire le terme "tableau", car il s'agit en réalité d'un arbre binaire )

    Et son opérateur ne va donc pas renvoyer la valeur dont l'indice est celui donné entre crochet, mais va effectuer la recherche approchée de la clé afin de renvoyer la valeur associée.

    Et, si, par malheur, la clé n'existe pas, il va la créer sans vergogne.

    Par "recherche approchée", je sais me tromper de terme (je ne l'ai plus en tete à l'instant), mais je veux indiquer le fait qu'il ne s'agit pas d'une vérification d'égalité.

    Ce n'est pas un test du genre de si (clé en cours == clé recherchée) qui est utilisé, mai un double test du genre de

    si ( clé en cours n'est pas plus petit que la clé recherchée ET clé recherchée n'est pas plus petit que la clé en cours), alors, c'est que la clé en cours est la clé recherchée.

    Et, là encore, ce que j'ai écrit plus haut devrait t'aider à comprendre pourquoi l'utilisation d'un réel en tant que clé n'est pas idéale, et pourquoi c'est encore un moins bon plan que d'essayer de le comparer... à un entier...

  5. #5
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Cela ne fait pas avancer le schmilblick mais je dit :
    très belle réponse koala01

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par ram-0000 Voir le message
    Cela ne fait pas avancer le schmilblick mais je dit :
    très belle réponse koala01
    Si, ca le fait avancer...

    Déjà, ma réponse précise (sans dire où il doit arriver) qu'il faut un dans la fonction principale.

    De plus, la réponse sous entend qu'il ne faut pas utiliser une std::map<double, double>, même si elle ne dit pas ce qu'il faut utiliser

    Allez, je suis bon prince, je proposerais une std::map<size_t, double> ou une std::map<size_t, size_t>

    Enfin, elle met en garde contre l'utilisation de l'opérateur []... Il est vrai qu'elle aurait pu donner une alternative, faisons le maintenant:

    Pour l'insertion, préférer insert sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mymap.insert(std::make_pair(key, value));
    Pour la recherche / sélection d'un élément : il faudrait préférer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::map<KeyType,ValueType>::iterator it=mymap.find(key);
    /* voire*/
    std::map<KeyType,ValueType>::const_iterator it = mymap.find(key);
    et pour obtenir la valeur associée à la clé, utiliser
    Maintenant que tu m'a forcé à tout mettre, le PO n'aura plus qu'à placer les bonnes instructions aux bons endroits

  7. #7
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Citation Envoyé par ram-0000 Voir le message
    Cela ne fait pas avancer le schmilblick mais je dit :
    très belle réponse koala01
    Si, ca le fait avancer...
    Pas de méprise, quand je disais "cela ne fait pas avancer le schmilblick", je parlai de mon post qui dit que ta réponse est jolie.

Discussions similaires

  1. [Std::map] Question sur les clés
    Par Kreeg dans le forum SL & STL
    Réponses: 1
    Dernier message: 26/02/2008, 22h32
  2. Questions sur les Shadow Maps
    Par funkydata dans le forum DirectX
    Réponses: 4
    Dernier message: 25/10/2007, 13h58
  3. Questions sur les std::string
    Par olive_le_malin dans le forum SL & STL
    Réponses: 6
    Dernier message: 23/02/2007, 08h44
  4. Question sur les specular maps
    Par funkydata dans le forum DirectX
    Réponses: 6
    Dernier message: 15/06/2006, 08h47
  5. Questions sur les Map
    Par djobanaille dans le forum C++
    Réponses: 3
    Dernier message: 12/12/2005, 09h41

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