Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

rand template

13 réponses
Avatar
Guillaume Gourdin
Comment est-ce que vous implémenteriez la fonction suivante ?

template <class T> T rand(const & T Max)

qui renvoie une valeur au hasard entre 0 et Max.

Merci.

10 réponses

1 2
Avatar
Fabien LE LEZ
On Sun, 20 Jul 2003 15:24:11 +0200, "Guillaume Gourdin"
wrote:

Comment est-ce que vous implémenteriez la fonction suivante ?

template <class T> T rand(const & T Max)


Honnêtement, je ne l'implémenterais pas. Etant donné la différence
d'implémentation entre short, int, double, etc., une telle fonction ne
se prête pas du tout à un template.


--
Tout sur fr.* (FAQ, etc.) : http://www.usenet-fr.net/fur/
et http://www.aminautes.org/forums/serveurs/tablefr.html
Archives : http://groups.google.com/advanced_group_search
http://www.usenet-fr.net/fur/usenet/repondre-sur-usenet.html

Avatar
Fabien LE LEZ
On Sun, 20 Jul 2003 17:19:37 +0200, "Vincent Lascaux"
wrote:

Mais qu'est ce
que ca veut dire un rand compris entre 0 (?) et un vecteur max, ou une
chaine de caracteres max ou même un complex max ?


C'est pour ça que je recommande d'éviter le template dans ce cas.

--
Tout sur fr.* (FAQ, etc.) : http://www.usenet-fr.net/fur/
et http://www.aminautes.org/forums/serveurs/tablefr.html
Archives : http://groups.google.com/advanced_group_search
http://www.usenet-fr.net/fur/usenet/repondre-sur-usenet.html

Avatar
Guillaume Gourdin
Avec ca on peut définir un rand sur tout et n'importe quoi... Mais qu'est
ce

que ca veut dire un rand compris entre 0 (?) et un vecteur max, ou une
chaine de caracteres max ou même un complex max ?


Pas grand chose, c'est sûr, mais bon, la classe complex est elle aussi
template, et un complex de vector, ça veut pas dire grand chose non plus.
C'est juste une commodité d'écriture pour justement ne pas avoir à spécifier
une fonction pour chaque type primitif.

Que pensez-vous de :

template<class > T rand(const T & Max)
{
if ( numeric_limits<T>::is_integer() ) return (rand() % Max);
else if ( numeric_limits<T>::is_bounded() ) return ( Max * (T)rand() /
(T)numeric_limits<T>::max() );
else assert(false);
}

Avatar
Guillaume Gourdin
Que pensez-vous de :

template<class > T rand(const T & Max)
{
if ( numeric_limits<T>::is_integer() ) return (rand() % Max);
else if ( numeric_limits<T>::is_bounded() ) return ( Max * (T)rand() /
(T)numeric_limits<T>::max() );
else assert(false);
}


Je pense même que l'assert(false) est de trop car le % et le / impliquent
des types primitifs (ou en tout cas numériques) (contre exemples ?).

Par ailleurs, j'ai implémenté une classe template<class T> COLOR. Comment
faire pour que numeric_limits<COLOR<int>>::is_integer() renvoie vrai et que
numeric_limits<COLOR<float>>::is_integer() renvoie faux ?

Avatar
Fabien LE LEZ
On Sun, 20 Jul 2003 20:59:25 +0200, "Guillaume Gourdin"
wrote:

template<class > T rand(const T & Max)
{
if ( numeric_limits<T>::is_integer() ) return (rand() % Max);


Si Max == RAND_MAX-2, compare la probabilité d'apparition de 0 par
rapport à celle de 2.
Quid si Max == RAND_MAX+1 ?


--
Tout sur fr.* (FAQ, etc.) : http://www.usenet-fr.net/fur/
et http://www.aminautes.org/forums/serveurs/tablefr.html
Archives : http://groups.google.com/advanced_group_search
http://www.usenet-fr.net/fur/usenet/repondre-sur-usenet.html

Avatar
Fabien LE LEZ
Ça ne répond pas totalement à la question, mais je propose une
implémentation (peu optimisée) pour double.

double NombreAleatoire (double minimum, double maximum)
{
double amplitude= maximum - minimum;
double reponse= 0;
double indicateur= amplitude;
double epsilon= (un nombre vraiment petit devant "amplitude");
while (fabs (indicateur) > epsilon)
{
reponse += indicateur * rand() / RAND_MAX;
indicateur/= RAND_MAX;
}

return reponse - minimum;
}

Je ne suis pas sûr que l'algo soit bon ; de plus, je ne connais pas la
valeur à donner à epsilon, mais ça devrait te donner une idée de la
complexité du truc... et de la difficulté à en faire un template.


--
Tout sur fr.* (FAQ, etc.) : http://www.usenet-fr.net/fur/
et http://www.aminautes.org/forums/serveurs/tablefr.html
Archives : http://groups.google.com/advanced_group_search
http://www.usenet-fr.net/fur/usenet/repondre-sur-usenet.html
Avatar
Richard Delorme
Guillaume Gourdin wrote:

Si Max == RAND_MAX-2, compare la probabilité d'apparition de 0 par
rapport à celle de 2.


Je ne vois pas où tu veux en venir...


Si rand() est un bon générateur, il renvoie des nombres entre 0 et RAND_MAX
- 1, avec une même probabilité.
Si Max == RAND_MAX - 2, 0 peut-être obtenu quand rand() renvoie 0 ou
RAND_MAX-2, ce qui rend 0 deux fois plus probable que beaucoup d'autre
nombres.

Quid si Max == RAND_MAX+1 ?


Oui, là, il y a un problème, Max ne sera jamais atteint.

Bon, que penses-tu de la fonction suivante, qui :
- s'il s'agit d'un entier, renvoie ( rand() * rand() ) % Max (plus de pb
de Max==RAND_MAX+1)


Si rand() est un bon générateur pseudo-aléatoire (valeurs renvoyées
équiprobables), rand() * rand() ne l'est plus (valeurs renvoyées non
équiprobables).

--
Richard


Avatar
Fabien LE LEZ
On Sun, 20 Jul 2003 21:52:59 +0200, "Guillaume Gourdin"
wrote:

Bon, supposons, pour simplifier, que RAND_MAX= (en pratique, c'est
plus proche de 2^15, mais le raisonnement est le même).

Si Max == RAND_MAX-2, compare la probabilité d'apparition de 0 par
rapport à celle de 2.


Je ne vois pas où tu veux en venir...


Max == 8

rand() renvoie, avec une probabilité égale [en théorie du moins] les
valeurs suivantes :

0 1 2 3 4 5 6 7 8 9

rand()%8 donnera donc :

0 1 2 3 4 5 6 7 0 1

Du coup, 0 a 20 % de chances de sortir, tandis que 2 n'en a que 10 %.

Quid si Max == RAND_MAX+1 ?


Oui, là, il y a un problème, Max ne sera jamais atteint.

Bon, que penses-tu de la fonction suivante, qui :
- s'il s'agit d'un entier, renvoie ( rand() * rand() ) % Max (plus de pb de
Max==RAND_MAX+1)


Ça favorise trop les petites valeurs, et en particulier 0 :

int rand_a= rand();
int rand_b= rand();

rand_a*rand_b == 0 si rand_a==0 ou rand_b==0
La proba que rand_a!=0 est ((RAND_MAX-1)/RAND_MAX)
La proba que rand_b!=0 est ((RAND_MAX-1)/RAND_MAX)
Donc, la proba que rand_a*rand_b!=0 est (RAND_MAX-1.)^2/RAND_MAX^2
Par conséquent, la proba que rand_a*rand_b==0 est
(2*RAND_MAX-1)/RAND_MAX^2 -- alors qu'en cas de distribution
équilibrée, la proba auraît du être de 1/RAND_MAX^2

Pour RAND_MAX==5, voici les chances de voir apparaître chaque nombre :

0 36 %
1 4 %
2 8 %
3 8 %
4 12 %
6 8 %
8 8 %
9 4 %
12 8 %
16 4 %
tous les autres 0 %



--
Tout sur fr.* (FAQ, etc.) : http://www.usenet-fr.net/fur/
et http://www.aminautes.org/forums/serveurs/tablefr.html
Archives : http://groups.google.com/advanced_group_search
http://www.usenet-fr.net/fur/usenet/repondre-sur-usenet.html


Avatar
Vincent Lascaux
Par ailleurs, j'ai implémenté une classe template<class T> COLOR. Comment
faire pour que numeric_limits<COLOR<int>>::is_integer() renvoie vrai et
que

numeric_limits<COLOR<float>>::is_integer() renvoie faux ?


template<class T>
class numeric_limits<COLOR<T>> : public numeric_limits<T> {};

Euh, j'attends quand même confirmation parceque je suis pas sur à 100%

--
Vincent

Avatar
Vincent Lascaux
template<class T>
class numeric_limits<COLOR<T>> : public numeric_limits<T> {};


Non, il faut une spécialisation, pas un héritage.


C'est une spécialisation et un héritage en même temps :-)


1 2