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 :

Utilisation de <random> avec une fonction statique


Sujet :

C++

  1. #1
    Membre averti
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Juillet 2018
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juillet 2018
    Messages : 27
    Par défaut Utilisation de <random> avec une fonction statique
    Bonjour la communauté,

    Je crée une classe Utilitaire dans laquelle je compte regrouper diverses fonctions statiques .
    La première d'entre elle doit retourner un entier "aléatoire" équiprobable compris entre [0, nbFace[

    Utilitaire.h
    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
     
    #ifndef UTILITAIRE_H
    #define UTILITAIRE_H
     
    #include<ctime>
    #include<random>
     
    class Utilitaire
    {
    public:
    // Constructeur
        Utilitaire();
     
    // Fonction statique
        static int jetDe(int nbFace, bool dejaVu=true);
     
    };
     
    #endif // UTILITAIRE_H
    Utilitaire.cpp
    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
    23
     
    #include "../Header_perso/Utilitaire.h"
     
    // Constructeurs
        Utilitaire::Utilitaire()
        {
     
        }
     
    // Lance un dé à nbFace
    int Utilitaire::jetDe(int nbFace, bool dejaVu)
    {
        if(nbFace<1) nbFace=1;
        std::default_random_engine lancer;
        std::uniform_int_distribution <int> leDe(0,nbFace-1);
        if(!dejaVu)
        {
            int timer = time(NULL);
            for(int i(0); i<timer%100; i++) leDe(lancer);
        }
        int tirage=leDe(lancer);
        return tirage;
    }
    le main pour tester la fonction statique jetDe
    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
     
    #include <iostream>
    #include "../Header_perso/Utilitaire.h"
     
    using namespace std;
     
    int main()
    {
        //initialisation aléatoire du dé
        int tirage=Utilitaire::jetDe(5,false);
        int i(10);
        while(i!=0)
        {
            tirage=Utilitaire::jetDe(10);
            cout << "tirage = " << tirage << endl;
            i--;
        }
    }
    Ça compile (code::blocks), avec le débugger l'appel à jetDe se passe bien mais tirage vaut systématiquement 0 et pas un entier "aléatoire" entre 0 et 9.
    Ça m'échappe... Une idée ?

    Rick.

  2. #2
    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,

    Déjà, pourquoi voudrais tu utiliser une fonction statique de classe dans le cas présent nous ne sommes pas en Java, et nous ne sommes donc pas obligé de passer par ce genre d'ineptie!!!

    Pourquoi ne pas plutôt définir une fonction libre dans un espace de noms D'autant plus que, étant donné le nom de la classe utilisé (Utilitaire), tu vas finir te retrouver avec une classe qui fournit un tas de fonctionnalités qui n'ont "rien à voir entre elles", purement et simplement "mégalithique", impossible à modifier par la suite.

    L'utilisation d'un espace de noms s'avère beaucoup plus cohérente dans le cas présent, ne serait ce que parce que cela te permettra de "classer" les différentes fonctionnalités "utilitaires" par "raison d'être", et donc de ne pas te retrouver à faire connaître 200 fonctions au compilateur lorsqu'il n'a besoin que d'en connaître qu'une ou deux

    Le principe serait donc d'avoir, dans un fichier d'en-tête (random_fonction.hpp, par exemple) un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #ifndef RANDOM_FUNCTION_HPP_INCLUDED
    #define RANDOM_FUNCTION_HPP_INCLUDED
    namespace Utitlitaires{
    int jetDes(int nbFace, bool dejaVu);
    }
    #endif
    et, dans un fichier d'implémentation (random_function.cpp, pour suivre l'exemple)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    namespace Utitlitaires{
    int jetDes(int nbFace, bool dejaVu){
        // le code qui va bien
    }
    }
    Ceci étant dit, pour répondre à ta question:

    Que ce soit dans une fonction statique ou dans une fonction libre, à l'intérieur d'un espace de noms, tu devrait déclarer ton std::default_random_engine lancer; comme étant statique, pour qu'il soit "gardé en mémoire" après le premier appel de la fonction et "réutilisé" lors des appels suivants.

    Autrement, à chaque appel de la fonction, ton std::default_random_engine sera , pour être automatiquement détruit lorsque l'on atteindra l'accolade fermante de la fonction, pour être créé une nouvelle de la même manière (en utilisant son constructeur par défaut) fois lors de l'appel suivant à la fonction.

    Or, la création d'un std::default_random_engine est parfaitement prédictible et reproductible : si tu le crée avec des valeurs identiques (les valeurs par défaut, dans le cas présent), la suite de valeurs qu'il utilise en interne sera identique, ce qui occasionne ton problème actuel .

    Note que le simple fait de déclarer ton std::default_random_engine ne résoudra sans doute qu'une partie de ton problème, car, si cela te permettra, effectivement, d'obtenir des valeurs différentes à chaque appel, ces valeurs seront exactement les mêmes à chaque fois que tu relanceras l'application, parce que, justement, la création de ce std::default_random_engine se fera toujours "de la même manière".

    Il se peut que ce soit le comportement que tu espères, mais je subodore que tu aimerais autant que les tirages lors de différentes exécutions de ton programmes soient différents

    Pour corriger ce "problème", l'idéal serait de créer ton std::default_random_engine avec des valeurs différentes lors de chaque exécution de ton programme. Le meilleur moyen pour y arriver étant d'utiliser std::time(nullptr) comme paramètre.

    Au final, cela te donnerait un code qui serait sans doute proche de
    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
    namespace Utilitaires{
    int jetDe(int nbFace, bool dejaVu)
    {
        if(nbFace<1) nbFace=1;
       static  std::default_random_engine lancer{std::time{nullptr}};
        std::uniform_int_distribution <int> leDe(0,nbFace-1);
        if(!dejaVu)
        {
            int timer = time(NULL);
            for(int i(0); i<timer%100; i++) leDe(lancer);
        }
        int tirage=leDe(lancer);
        return tirage;
    }
    }
    (au erreurs possibles près, je n'ai pas testé ce code )
    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

  3. #3
    Membre averti
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Juillet 2018
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juillet 2018
    Messages : 27
    Par défaut
    Merci koala01 pour cette réponse détaillée.

    Je vais essayer l'espace de nom comme tu le suggères.
    Si j'y arrive en suivant tes conseils je reviens placer de suite cette discussion en résolu.

    Rick.

    [edit]
    Succès total ! Je passe le topic en "résolu" Merci encore.

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 03/03/2010, 19h05
  2. Onclick avec une fonction utilisant $(this)
    Par Calvein dans le forum jQuery
    Réponses: 5
    Dernier message: 20/01/2009, 16h04
  3. Réponses: 0
    Dernier message: 22/07/2008, 17h47
  4. Problème avec une fonction en utilisant Zsh
    Par Olivier Regnier dans le forum Shell et commandes GNU
    Réponses: 2
    Dernier message: 18/06/2007, 08h19
  5. Problème avec une Fonction utilisant WMI
    Par Eric_78180 dans le forum VBScript
    Réponses: 3
    Dernier message: 29/12/2006, 14h00

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