Entra

View Full Version : [C++] Generare un numero random


AngeL)
28-06-2006, 08:32
come si fa a generare un numero random in C++? quali file si devono includere?
Grazie in anticipo

Andlea
28-06-2006, 08:45
#include <time.h>

srand(time(NULL));
a=rand()%range;

range è un numero positivo, che determina il range in cui il numero viene creato
La funzione restituisce un int tra 0 e range

rand()%range-range; // Numeri negativi
rand()%range-range/2; // Numeri positivi e negativi nell'intorno di 0 con massimo in range/2
ecc...

AngeL)
28-06-2006, 08:50
grazie.
che significa
srand(time(null)); ?

andbin
28-06-2006, 09:07
che significa
srand(time(null)); ?srand serve per impostare il "seme" per la generazione della sequenza di numeri pseudo-casuali. Passando alla srand la data/ora corrente, si imposta in questo modo un "buon" seme "casuale".

AngeL)
28-06-2006, 09:12
grazie a tutti e due gli andrea :D

midget
28-06-2006, 14:56
In questa pagina (http://members.cox.net/srice1/random/crandom.html) ci sono delle precisazioni molto interessanti per ottenere un numero casuale in maniera corretta.

In particolare si sottolinea questo:
Do NOT use
y = rand() % M;


Ciao ;)

trallallero
28-06-2006, 15:47
In questa pagina (http://members.cox.net/srice1/random/crandom.html) ci sono delle precisazioni molto interessanti per ottenere un numero casuale in maniera corretta.

In particolare si sottolinea questo:


Ciao ;)

e perché mai ???
io come al solito ho: Accesso negato :muro:

midget
29-06-2006, 10:43
Quella pagina lo spiega in modo esauriente, a me funziona, ho appena provato.

Comunque in sintesi facendo il modulo si ottiene una correlazione tra il numero generato con solo i bit inferiori restituiti da rand() che "generalmente" sono molto meno casuali dei bit superiori. Ovviamente e' possibile che la specifica implementazione di rand() delle librerie che si vanno ad utilizzare abbia un comportamento diverso (eventualmente migliore).
Le formule indicate nella pagina citata servono per essere sicuri di utilizzare comunque tutti i bit generati da rand() a prescindere dall'implementazione.

Ciao ;)

trallallero
29-06-2006, 11:07
Quella pagina lo spiega in modo esauriente, a me funziona, ho appena provato.

Comunque in sintesi facendo il modulo si ottiene una correlazione tra il numero generato con solo i bit inferiori restituiti da rand() che "generalmente" sono molto meno casuali dei bit superiori. Ovviamente e' possibile che la specifica implementazione di rand() delle librerie che si vanno ad utilizzare abbia un comportamento diverso (eventualmente migliore).
Le formule indicate nella pagina citata servono per essere sicuri di utilizzare comunque tutti i bit generati da rand() a prescindere dall'implementazione.

Ciao ;)
come fai a dire che a te funziona ?
se i bit inferiori sono meno casuali avrai una differenza sul numero di probabilitá
che riesca un dato numero. Non la totale assenza di quel numero.
O forse ho capito male ? :confused:

midget
29-06-2006, 11:46
come fai a dire che a te funziona ?
Mi riferivo alla pagina web, avevo capito che ti dava accesso negato.
I suggerimenti dati a quella pagina li ho gia' applicati con successo diverse volte.

se i bit inferiori sono meno casuali avrai una differenza sul numero di probabilitá
che riesca un dato numero. Non la totale assenza di quel numero.
Si infatti, avrai un numero casuale meno "buono".

Questo pero' e' un punto fondamentale e da non trascurare quando si utilizzano numeri casuali in applicazioni in ambito sicurezza.

Analogamente se servono numeri casuali per la generazioni di "eventi" per testare un qualche tipo di procedura o algoritmo o altro, se i numeri generati non sono sufficientemente "buoni", tutta la procedura di test o di misurazione potrebbe risultare invalidata.

Sempre nella stessa pagina vengono fatti notare anche alcuni rischi di overflow da tenere presenti e risolvibili con alcuni cast espliciti.

Ciao ;)

trallallero
29-06-2006, 12:11
Mi riferivo alla pagina web, avevo capito che ti dava accesso negato.
ah, avevo capito male :D

Comunque ho fatto un programmino di test su numeri da 0 a 9, 1000 volte e sembra tutto ok.

Mat[0]: <97>
Mat[1]: <100>
Mat[2]: <96>
Mat[3]: <99>
Mat[4]: <101>
Mat[5]: <107>
Mat[6]: <82>
Mat[7]: <113>
Mat[8]: <110>
Mat[9]: <95>

tutti intorno alle 100 volte. Se fossero stati tutti 100 volte precise mi sarei preoccupato :eek:

ciao :)

midget
29-06-2006, 12:48
Controlla anche in che sequenza ti escono i numeri, potrebbe avere delle periodicita'' che con il tuo test non vedi (su quel sito dice che potrebbero uscire alternati pari-dispari)

Ciao ;)

AngeL)
29-06-2006, 12:50
alcuni usano
#define RAND_MAX 50
x = rand();

(non so se funziona)

andbin
29-06-2006, 13:02
alcuni usano
#define RAND_MAX 50
x = rand();No, RAND_MAX non lo puoi definire tu ... è una costante dichiarata nell'include stdlib.h ed è comunque "cablato" all'interno della rand().

trallallero
29-06-2006, 13:05
No, RAND_MAX non lo puoi definire tu ... è una costante dichiarata nell'include stdlib.h ed è comunque "cablato" all'interno della rand().

"cablato" ? cioé :confused:

andbin
29-06-2006, 13:28
"cablato" ? cioé :confused:La funzione rand() usa certamente al suo interno il valore di RAND_MAX .... quindi il valore è "cablato" nel suo codice!

EDIT: alt, bisogna anche vedere come è stata implementata la rand()!!!

AngeL)
29-06-2006, 13:30
un mio amico mi ha dato un codice con rand_max che effettivamente faceva restituire a rand un valore entro rand_max... :confused: :confused: :confused:

Ziosilvio
29-06-2006, 13:34
come si fa a generare un numero random in C++?
Si consulta questa guida (http://www.hwupgrade.it/forum/showthread.php?t=1196677) ;)

E se si hanno idee, suggerimenti, avvisi, lamentele ecc., si è i benvenuti ;)

AngeL)
29-06-2006, 13:41
oops :doh:

trallallero
29-06-2006, 14:02
La funzione rand() usa certamente al suo interno il valore di RAND_MAX .... quindi il valore è "cablato" nel suo codice!
vabbé non é quello che impedisce la ridefinizione di RAND_MAX. Pensavo intendessi qualcos'altro

Ci ho provato (#define RAND_MAX 10) mi da giustamente un warning sulla define
ma poi non me la caga proprio :)
Non mi considera proprio :D

andbin
29-06-2006, 14:19
vabbé non é quello che impedisce la ridefinizione di RAND_MAX. Pensavo intendessi qualcos'altro

Ci ho provato (#define RAND_MAX 10) mi da giustamente un warning sulla define
ma poi non me la caga proprio :)
Non mi considera proprio :DA parte il fatto che se vuoi ridefinire una macro già esistente, devi prima fare un #undef ...

Comunque il problema non è quello!
Sono andato adesso a vedere il sorgente della rand() nel VC++. Eccolo:
int __cdecl rand (
void
)
{
#ifdef _MT

_ptiddata ptd = _getptd();

return( ((ptd->_holdrand = ptd->_holdrand * 214013L
+ 2531011L) >> 16) & 0x7fff );

#else /* _MT */
return(((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
#endif /* _MT */
}Vedi che il valore di ritorno viene sempre troncato con un & 0x7fff??? Vuol dire che il comportamento di questa rand() è quello di ritornare un valore tra 0 e 32767.

E nell'include stdlib.h fornito con il VC++ c'è:
#define RAND_MAX 0x7fff

Se anche tu ridefinissi RAND_MAX, la funzione rand() continua a funzionare secondo il modo con cui è stata progettata e compilata!!!!!!

trallallero
29-06-2006, 14:34
A parte il fatto che se vuoi ridefinire una macro già esistente, devi prima fare un #undef ...
vabbé quello é solo per evitare il warning

Comunque il problema non è quello!
Sono andato adesso a vedere il sorgente della rand() nel VC++. Eccolo:
int __cdecl rand (
void
)
{
#ifdef _MT

_ptiddata ptd = _getptd();

return( ((ptd->_holdrand = ptd->_holdrand * 214013L
+ 2531011L) >> 16) & 0x7fff );

#else /* _MT */
return(((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
#endif /* _MT */
}Vedi che il valore di ritorno viene sempre troncato con un & 0x7fff??? Vuol dire che il comportamento di questa rand() è quello di ritornare un valore tra 0 e 32767.

E nell'include stdlib.h fornito con il VC++ c'è:
#define RAND_MAX 0x7fff

Se anche tu ridefinissi RAND_MAX, la funzione rand() continua a funzionare secondo il modo con cui è stata progettata e compilata!!!!!!
ma bene! che bello vedere le costanti nel codice :rolleyes:

tomminno
30-06-2006, 10:04
Se vi serve un generatore di numeri casuali che rispetti un minimo di requisiti di casualità andatevi a leggere i Numerical Recipes, senza perdere troppo tempo su rand().

AngeL)
30-06-2006, 17:52
ho un problema... il compilatore dice che null non è definito... questa è la funzione
int randgen()
{
srand(time(null));
return rand()%4+1;
}
help :cry:

Energy++
30-06-2006, 18:05
Semplice ti da errore perche lo devi scrivere tutto maiuscolo!! ;)

NULL

ciao ciao :p :Prrr:

AngeL)
30-06-2006, 18:06
ehm.. :mc: :mc: :muro: :muro: :muro: :muro: scusa :D :muro: :muro:

AngeL)
30-06-2006, 18:25
ho scritto una funzione che scrive 100 volte il risultato di randgen e mi esce lo stesso numero... dove ho sbagliato?

Energy++
30-06-2006, 18:56
ho scritto una funzione che scrive 100 volte il risultato di randgen e mi esce lo stesso numero... dove ho sbagliato?

così dovrebbe andare:

int randgen()
{
return rand()%4+1;
}

main(){
srand(time(NULL));
for(int i=0; i<101; i++)
cout <<randgen()<<endl;
system("pause");
}

ciao ciao

Ziosilvio
01-07-2006, 10:20
il compilatore dice che null non è definito
null non è definito. NULL, invece, sì --- e il C è case-sensitive.
return rand()%4+1;
:nonsifa:
return (rand()/(RAND_MAX+1.0))*4+1;
:read: qui (http://www.hwupgrade.it/forum/showthread.php?t=1196677)

Ziosilvio
01-07-2006, 10:23
ho scritto una funzione che scrive 100 volte il risultato di randgen e mi esce lo stesso numero... dove ho sbagliato?
Se non viene specificato altrimenti, il generatore pseudorandom viene sempre inizializzato col valore di default, quindi a ogni nuova esecuzione la sequenza è sempre la stessa.
Il problema si risolve inizializzandolo con un valore diverso a ogni esecuzione: il modo classico srand(time(NULL)), in base all'ora di sistema, ma ho visto fare anche srand(getpid()), in base al PID del processo in corso.

AngeL)
01-07-2006, 10:50
così dovrebbe andare:

int randgen()
{
return rand()%4+1;
}

main(){
srand(time(NULL));
for(int i=0; i<101; i++)
cout <<randgen()<<endl;
system("pause");
}

ciao ciao

il mio codice è uguale.

non return rand()%4+1 ma return (rand()/(RAND_MAX+1.0))*4+1;

che cambia? :mbe:

edit: ho fatto cosi #include <iostream>
#include <time.h>
using namespace std;

int randgen();

int main()
{
int i;
for(i=0;i<10;i++)
{
cout << randgen() << endl;
}
}

int randgen()
{
srand(time(NULL));
return (rand()/(RAND_MAX+1.0))*4+1;
}
ma restituisce sempre lo stesso numero :\

andbin
01-07-2006, 11:01
ma restituisce sempre lo stesso numero :\srand la devi chiamare 1 volta sola all'inizio del programma.

AngeL)
01-07-2006, 11:18
grazie :)

Energy++
01-07-2006, 19:05
srand la devi chiamare 1 volta sola all'inizio del programma.


si infatti

Ziosilvio
01-07-2006, 23:07
che cambia?
Che usi tutte le cifre usate da rand, anziché solo quelle meno significative.
In questo modo, la qualità del generatore che ottieni, è confrontabile con quella di rand; nell'altro modo, rischi di ottenere un generatore anche molto peggiore.