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 :

Fonction impure et générateur aléatoire


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Par défaut Fonction impure et générateur aléatoire
    Salut à toutes et à tous !

    Quelle syntaxe est à préférer lorsque l'on crée des foncteurs de simulation pour lesquels des générateurs de nombre aléatoires sont nécessaires ?

    Transmettre le générateur à l'appel de fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    std::mt19937 gen;
    auto f = [](auto& generator, int arg){ return some_simulation_code(generator, arg); };
    f(gen, 3);
    ou transmettre le générateur à la construction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    std::mt19937 gen;
    auto g = [& gen](int arg){ return some_simulation_code(gen, arg); };
    g(3);


    Mon sentiment est que peut-être que j'aimerais bien me rappeler à l'appel de la fonction qu'elle ne renverra pas deux fois la même chose, et que j'aimerais coller un peu à la syntaxe de la STL qui file le générateur à l'appel de l'opérateur (il doit y avoir une raison pour laquelle ils font ça ).

    D'un autre côté quand pas mal de code repose sur l'interface operator()(int), et que le modèle mathématique sous jacent est défini par des fonctions d'entiers, j'imagine qu'on peut légitimement mettre un générateur en membre de classe pour garder une certaine uniformité ?

    Mais d'encore un autre côté la construction du foncteur peut avoir lieu à un endroit éloigné de là où est construit le générateur (pour l'instant c'est pas trop le cas), du coup ça peut valoir le coup de retarder le moment où les deux se rencontrent.

    Quelle est la manière standard de faire ? (celle de la STL j'imagine ).
    Bien à vous,

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 151
    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 151
    Billets dans le blog
    4
    Par défaut
    Salut,

    Citation Envoyé par Seabirds Voir le message
    Mon sentiment est que peut-être que j'aimerais bien me rappeler à l'appel de la fonction qu'elle ne renverra pas deux fois la même chose
    C'est quasiment part du contrat avec un générateur. Un générateur qui retournerait plusieurs fois la même valeur, y'a sûrement un problème dedans.
    Si tu veux avoir un truc plus clair, commence par ne pas nommer ton foncteur g mais generateRandomValue.

    Citation Envoyé par Seabirds Voir le message
    , et que j'aimerais coller un peu à la syntaxe de la STL qui file le générateur à l'appel de l'opérateur (il doit y avoir une raison pour laquelle ils font ça ).
    Il font ça parce qu'il faut bien que l'algo de la distribution (qui sélectionne le nombre) sache de quel générateur il doit le tirer.
    La distribution ne fait aucun tirage aléatoire. Elle se charge d'appliquer modulos etc nécessaires à avoir le résultat souhaité (entier borné, réel, ...).

    Citation Envoyé par Seabirds Voir le message
    D'un autre côté quand pas mal de code repose sur l'interface operator()(int), et que le modèle mathématique sous jacent est défini par des fonctions d'entiers, j'imagine qu'on peut légitimement mettre un générateur en membre de classe pour garder une certaine uniformité ?
    Si tu conserves pas le générateur en tant que membre, comment comptes-tu l'utiliser ?
    En créer un à chaque fois et l'initialiser avec une nouvelle seed ?
    Le mettre en variable membre ou pas n'est pas une solution à tirer à pile ou face mais doit avoir du sens.

    Citation Envoyé par Seabirds Voir le message
    Mais d'encore un autre côté la construction du foncteur peut avoir lieu à un endroit éloigné de là où est construit le générateur (pour l'instant c'est pas trop le cas), du coup ça peut valoir le coup de retarder le moment où les deux se rencontrent.
    Comment peux-tu ignorer où initialiser et sauvegarder le générateur ?
    S'il doit être membre de la classe, fais-en une variable membre. Et dans ce cas, pourquoi initialiser un foncteur je ne sais où et ne pas avoir une fonction membre qui génère le nombre ?
    S'il n'a pas à être membre, crée-le quand tu en as besoin. Et dans ce cas pourquoi n'as-tu pas besoin de ton foncteur de sélection de nombre directement ? Parce que tu crées le générateur trop tôt ? Le foncteur trop tard ?

    Citation Envoyé par Seabirds Voir le message
    Quelle est la manière standard de faire ? (celle de la STL j'imagine ).
    La STL en a choisi une. Afin de découpler totalement générateur et distribution.
    En pratique, je n'ai jamais vu un tel découplage nécessaire. Une distribution n'a du sens qu'avec un générateur, et un générateur est utilisé avec un seul type de distribution dans la plupart des cas.
    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.

  3. #3
    Membre éclairé Avatar de Seabirds
    Homme Profil pro
    Post-doctoral fellow
    Inscrit en
    Avril 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Post-doctoral fellow
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2015
    Messages : 294
    Par défaut
    Salut Bousk ! Merci de ta réponse

    Citation Envoyé par Bousk Voir le message
    Si tu veux avoir un truc plus clair, commence par ne pas nommer ton foncteur g mais generateRandomValue.
    Oups oui c'est le cas dans mon code, pour l'exemple j'ai mis des noms bidon. Au temps pour moi.

    Citation Envoyé par Bousk Voir le message
    Si tu conserves pas le générateur en tant que membre, comment comptes-tu l'utiliser ?
    En créer un à chaque fois et l'initialiser avec une nouvelle seed ?
    Heu non, en le passant comme argument d'une fonction membre.

    Citation Envoyé par Bousk Voir le message
    Le mettre en variable membre ou pas n'est pas une solution à tirer à pile ou face mais doit avoir du sens.
    Tout à fait d'accord, c'est pour ça que je pose la question pour clarifier le sens que je veux donner.

    Citation Envoyé par Bousk Voir le message
    Comment peux-tu ignorer où initialiser et sauvegarder le générateur ?
    Parce que j'ai codé tout un petit tas de fonctionnalités que j'appelerais bien présomptueusement une bibliothèque, et que là je suis dans le code d'un petit programme de démo qui utilise la bibliothèque.
    Du coup pour l'instant j'ai un gros corps de fonction dégueu de 100 lignes de long où tout est initialisé au même endroit. Tu as raison le problème vient de là, j'y verrai plus clair quand ce sera plus organisé

    Citation Envoyé par Bousk Voir le message
    S'il doit être membre de la classe, fais-en une variable membre. Et dans ce cas, pourquoi initialiser un foncteur je ne sais où et ne pas avoir une fonction membre qui génère le nombre ?
    Pourquoi ça semble évident une fois que c'est dit ?

    Ok, donc imaginons que j'ai une grosse classe A qui fait la simulation générale en appelant des fonctions membres qui font des petits bouts de la grosse simulation. Dans ce cas il y a un sens à faire le générateur membre de A, et initialisé à la construction d'une instance de simulation. Hum je crois que j'ai compris.

    Citation Envoyé par Bousk Voir le message
    La STL en a choisi une. Afin de découpler totalement générateur et distribution.
    En pratique, je n'ai jamais vu un tel découplage nécessaire. Une distribution n'a du sens qu'avec un générateur, et un générateur est utilisé avec un seul type de distribution dans la plupart des cas.
    Je crois que c'est le genre de réponse que je cherchais ! Merci !

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,
    Citation Envoyé par Seabirds Voir le message
    Heu non, en le passant comme argument d'une fonction membre.
    D'accord, mais, pourquoi voudrais tu le fournir comme paramètre à ta fonction membre

    Les paramètres d'une fonction, c'est très bien pour apporter un "point de variation" dans les données utilisées par la fonction.

    Par exemple, si tu veux envoyer tes donner dans un flux, mais que tu ne sais pas, au moment où tu écris ta fonction, si le flux en question doit être un fichier, la sortie standard ou un flux réseau.

    Au final, la question devient donc
    Souhaites tu, avec la même instance de ta classe, pouvoir faire plusieurs appels à ta fonction avec plusieurs générateurs, ou prévois tu, au contraire, d'utiliser toujours le même

    Voire, souhaites tu pouvoir utiliser le même générateur avec plusieurs instances de ta classe
    Ce sera la réponse à cette question qui te permettra de déterminer l'endroit où ton générateur doit être créé:
    • si chaque instance de ta classe utilise un générateur différent, mais que chaque appel à la fonction à partir d'une instance particulière de ta classe utilise toujours le même générateur, fais en une donnée membre et crée le dans le constructeur de ta classe.
    • si plusieurs instances de ta classe doivent pouvoir utiliser le même générateur, fais en une donnée membre sous forme de référence, et fournis le comme paramètre au constructeur de ta classe
    • si chaque appel à la fonction (quelle que soit l'instance à partir de laquelle la fonction est appelée, finalement) peut utiliser un générateur différent, fais en un paramètre de la fonction
    • si chaque foncteur (expression lambda) utilisé(e) peut utiliser un générateur différent (parce que ce qui t'intéresse, c'est la valeur aléatoire, et non la manière dont elle est générée), fais en sorte que le générateur soit "transparent" pour l'appel de la fonction (en utilisant une std::function<void()> au lieu d'une std::function<void(some_generator)>si le choix ne dépend pas de toi, mais des circonstances, transforme ta classe en classe template, et utilise des politiques et des traits pour ajouter les points de variation nécessaires



    Tout à fait d'accord, c'est pour ça que je pose la question pour clarifier le sens que je veux donner.

    Pourquoi ça semble évident une fois que c'est dit ?
    Parce qu'il fallait le dire pour que tu t'en rendes comptes
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

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

Discussions similaires

  1. Réponses: 8
    Dernier message: 05/07/2010, 19h59
  2. Réponses: 1
    Dernier message: 21/09/2009, 08h24
  3. Problèmes avec Gfortran g95 (générateur aléatoire)
    Par genie_civil2006 dans le forum Fortran
    Réponses: 1
    Dernier message: 04/08/2009, 16h03
  4. [z/OS] Générateur aléatoire sous Cobol
    Par vivia363 dans le forum Cobol
    Réponses: 1
    Dernier message: 25/07/2007, 21h23
  5. Réponses: 2
    Dernier message: 08/06/2007, 09h27

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