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 :

Problème avec std::multiplies


Sujet :

SL & STL C++

  1. #1
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut Problème avec std::multiplies
    Bonjour,

    je souhaiterai multiplier chaque élément d'un vector en utilisant la fonction STL std::multiplies, mais j'ai un peu de mal à la faire fonctionner. Voici comment je m'y prend :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    std::vector <int> ivec;
    ivec.push_back (1);
    ivec.push_back (2);
    ivec.push_back (3);
    ivec.push_back (4);
     
    std::for_each(ivec.begin(), ivec.end(), std::bind2nd(std::multiplies <int>(), 2));
     
    std::cout << ivec[0] << ' ' << ivec[1] << ' ' << ivec[2] << ' ' << ivec[3];
    Hélas, mes valeurs restent les mêmes qu'au début :/. Sinon, j'aimerais savoir la différence entre std::bind2nd et std::bind1st, car en essayant tout à l'heure une fonction, ça me donnait le même résultat qu'elle que soit le bind utiliser.

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    258
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 258
    Par défaut
    multiplies renvoie la valeur multipliée : tes valeurs sont effectivement doublée, mais le résultat est perdu. Tu peux résoudre le problème avec std::transform, en passant comme destination ton vecteur ivec.

  3. #3
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    J'ai essayé ça :

    std::transform (ivec.begin(), ivec.end(), std::bind1st (std::multiplies <int>(), 2);
    std::transform (ivec.begin(), ivec.end(), std::bind2nd (std::multiplies <int>(), 2);

    Mais aucune des deux solutions ne marchent, la syntaxe n'est certainement pas bonne, tu n'aurais pas un exemple.

    Sinon, niveau performance ça donne quoi, est-ce mieux de faire une technique comme ça en utilisant abusivement les fonctions de la STL ou une simple boucle for dans laquelle on multiplie chaque élément ? Notamment sur des gros tableaux et des petits tableuax ?

    EDIT : et avec cette méthode que je viens d'essayer et qui elle marche bien :

    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
    template <typename T>
    void Mult (T & val)
    {
       val *= 2;
    }
     
    int main()
    {
       std::vector <int> ivec;
       ivec.push_back (1);
       ivec.push_back (2);
       ivec.push_back (3);
       ivec.push_back (4);
     
       std::for_each (ivec.begin(), ivec.end(), Mult <int>);
     
       std::cout << ivec[0] << ' ' << ivec[1] << ' ' << ivec[2] << ' ' << ivec [3];
     
       return 0;
    }

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    258
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 258
    Par défaut
    Citation Envoyé par Bakura
    J'ai essayé ça :

    std::transform (ivec.begin(), ivec.end(), std::bind1st (std::multiplies <int>(), 2);
    std::transform (ivec.begin(), ivec.end(), std::bind2nd (std::multiplies <int>(), 2);
    transform prend un paramètre en plus pour la destination.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    std::transform (ivec.begin(), ivec.end(), ivec.begin(), std::bind1st (std::multiplies <int>(), 2);
    Citation Envoyé par Bakura
    Sinon, niveau performance ça donne quoi, est-ce mieux de faire une technique comme ça en utilisant abusivement les fonctions de la STL ou une simple boucle for dans laquelle on multiplie chaque élément ? Notamment sur des gros tableaux et des petits tableuax ?
    D'après ce que j'ai pu voir dans mon code, c'est un peu plus lent qu'une simple boucle for. Comme d'habitude, il y a un équilibre à trouver entre vitesse nécessaire et abstraction/généricité.

  5. #5
    Membre chevronné
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    258
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 258
    Par défaut
    Citation Envoyé par Bakura
    Sinon, j'aimerais savoir la différence entre std::bind2nd et std::bind1st, car en essayant tout à l'heure une fonction, ça me donnait le même résultat qu'elle que soit le bind utiliser.
    bind1st fixe le premier argument de multiplies, tandis que bind2nd fixe le second. Dans ton cas, puisque tu multiplies des int, le résultat est le même.

  6. #6
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Merci, en effet ça marche .

    J'aimerais avoir d'autres avis sur la rapidité entre les trois fonctions que j'ai montré plus haut.

    C'est assez dur de voir, mais quand je lance le profiler avec soit la méthode du for_each et une fonction template pour multiplier ou soit celle du std::transform + std::bind2nd + std::multiplies, ça fait assez peur . C'est rempli d'appels aux noms très étranges , alors qu'avec une boucle for ya presque rien.

    En voyant le profiler j'aurais tendance à dire comme toi qu'une boucle for est plus rapide, surtout pour des petits tableaux, mais en fait j'en suis pas sûr, les trucs les plus compliqués sont parfois (souvent ?) plus rapides.

  7. #7
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    A priori je dirais que si tout est bien inliné, il n'y a pas de raison d'avoir moins de performance.

    Par contre, ce style de programmation c'est de la programmation fonctionnelle, mais assez lourde à manier à cause du manque d'inférence de type ici.

    Tu devrais essayer avec boost.lambda, ce serait peut-être plus lisible.

  8. #8
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Bon je viens de lire un petit extrait de Effective STL, et ils disent qu'utiliser les algorithmes de la STL était plus rapide que faire des boucles, moins sujet à erreurs qu'écrire ses propres boucles et plus maintenable.

    Pour la performance, ils soulignent ça :

    for (list<Widget>::iterator i = lw.begin(); i != lw.end(); ++ i){
    i->redraw();
    }
    I've highlighted the loop termination test to emphasize that each time around the loop,
    i will be checked against lw.end(). That means that each time around the loop, the
    function list-end will be invoked. But we don't need to call end more than once,
    because we're not modifying the list.
    Et que visiblement la fonction for_each par exemple optimise mieux ça.

    Ils disent aussi que les algos de la STL peuvent prendre parti du fait qu'ils connaissent l'implémentation du container et enfin que, je cite :

    STL algorithms use computer science algorithms that are more sophisticated — sometimes much more sophisticated — than anything the average C++ programmer will be able to come up with.
    Voilà, bon après le mieux c'est de faire des tests .

  9. #9
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Oui, enfin parfois, il m'est arrivé que des implémentations de la STL me déçoivent, notamment celle de G++ version 4.1.2 avec pas mal d'inlining, pour la fonction merge.

    Pour des vecteurs, c'était bien plus rapide de faire la fusion manuelle de 2 vecteurs dans un nouveau avec des indices, qu'avec des itérateurs. J'aurais espéré que la différence de vitesse soit négligeable par rapport aux itérateurs, mais pas vraiment.

    Je sais pas si c'est un problème de compilateur, ou de je ne sais quoi d'autre.

    Heureusement la plupart du temps, la STL fait souvent bien mieux que nous à la main .

Discussions similaires

  1. Problème avec std::find_if
    Par camboui dans le forum SL & STL
    Réponses: 3
    Dernier message: 10/12/2008, 17h12
  2. Problème avec std::string
    Par Laughing Man dans le forum C++
    Réponses: 18
    Dernier message: 07/02/2008, 19h04
  3. problème avec std::cin
    Par _LVEB_ dans le forum SL & STL
    Réponses: 4
    Dernier message: 20/02/2007, 00h35
  4. Problème avec std::vector
    Par dhoorens dans le forum SL & STL
    Réponses: 4
    Dernier message: 31/12/2006, 14h27
  5. Problème avec std::Vector
    Par mister3957 dans le forum SL & STL
    Réponses: 8
    Dernier message: 16/02/2006, 10h18

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