[C] Funzionamentodella funzione rand()

Suwako27
sera, vorrei avere qualche chiarimento sul generatore di numeri casuali:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
	
	srand(time(NULL));
	int N = rand()%(200-100) + 100;
unsigned int counter = 0;
		for(unsigned int i = 0; i < N; i++)
		{
			printf("%d-", rand()%(200-100) + 100);
			counter++;
		}
	printf("\n\n %d numeri stampati", counter);
vorrei fare in modo che vengano stampati numeri un numero massimo di volte compreso l'intervallo tra 100 e 200. Tecnicamente lo fa ma non sembra farlo in maniera randomica, cioè ogni secondo il numero casuale generato aumenta di 3 per poi ritornare al minimo una volta raggiunto il numero massimo, quindi non funziona allo stesso modo di quando genera i numeri da stampare.

Risposte
DeltaEpsilon
"Suwako27":

Tecnicamente lo fa ma non sembra farlo in maniera randomica, cioè ogni secondo il numero casuale generato aumenta di 3 per poi ritornare al minimo una volta raggiunto il numero massimo

Che vuol dire "ogni secondo"? Il programma che hai scritto di certo non ferma il thread sul quale sta lavorando, quindi intendevi dire che "ogni secondo" avvii di nuovo il programma?

"Suwako27":

quindi non funziona allo stesso modo di quando genera i numeri da stampare.

Ma cos'è che non funziona allo stesso modo della stampa degli N numeri casuali?





Sarò io, ma sinceramente non ci ho capito niente...

Suwako27
Che vuol dire "ogni secondo"? Il programma che hai scritto di certo non ferma il thread sul quale sta lavorando, quindi intendevi dire che "ogni secondo" avvii di nuovo il programma?
esatto :roll:
Ma cos'è che non funziona allo stesso modo della stampa degli N numeri casuali?
intendevo che la le due funzioni rand apparentemente non funzionano allo stesso modo.
Sarò io, ma sinceramente non ci ho capito niente...

:(

DeltaEpsilon
"Suwako27":

intendevo che la le due funzioni rand apparentemente non funzionano allo stesso modo.

Ma perché? Cosa succede? E cosa invece ti aspettavi?

Suwako27
che se avvio il programma vedo che i numeri stampati sono casuali(es 116-178-130-ecc...) ma il numero di volte che vengono stampati, cioè il numero N non è proprio casuale, infatti quando avvio il programma più volte di seguito il counter non è casuale: esempio se prima mi stampa 130 numeri, al secondo avvio subito sono 133. Non so se rendo l'idea

DeltaEpsilon
Il comportamento che stai descrivendo, per quanto anomalo possa sembrare, è pur sempre pseudocasuale.

Non puoi aspettarti che ciò che vedi avvenga allo stesso modo per tutti e per sempre.

Sulla mia macchina, ad esempio, avviando il programma per tre volte il valore di N è 199, 116, 197 che è ben diverso, prevedibilmente, da quel che tu descrivi.

Suwako27
Infatti è proprio quello il problema. Posso capire che ciò dipenda da dove e come , però una cosa è su due computer diversi, un' altra è se sono nello stesso codice.

vict85
Se vuoi che il programma generi sempre la stessa sequenza dovresti usare una costante nella funzione [inline]srand[/inline]. Detto questo lo standard non definisce alcun algoritmo specifico, quindi due funzioni [inline]rand[/inline] di due librerie diverse possono avere comportamenti molto diversi. La funzione [inline]rand[/inline], tra l'altro, non ha alcuna pretesa di essere un buon generatore di numeri pseudo-casuali.

A questo si aggiunge il fatto che [inline]rand[/inline] genera numeri pseudo-casuali nel range [inline][0, RAND_MAX][/inline]. Quindi anche supponendo che rand generi numeri con una probabilità uniforme in quel range, non è affatto vero che la funzione [inline]rand()%100 + 100[/inline] genera numeri uniformamente in [inline][100, 199][/inline], anzi se [inline]RAND_MAX+1[/inline] non è divisibile per 100 sai per certo che non lo farà. Se hai bisogno che sia uniforme, allora devi usare un algoritmo più complesso del solo modulo.

vict85
Riguardo invece a N, il tuo pc non sta facendo girare solo la funzione rand. Inoltre non c'è ragione per pensare che la funzione rand faccia sempre la stessa quantità di operazioni. Non capisco perché ti aspetti performance costanti.

Suwako27
Io non mi aspetto performance costanti, solamente non capivo perché le due funzioni rand danno risultati diversi: quella che genera i vari elementi funziona come previsto, ma quella che stabilisce N è "prevedibile": cioè se avvio il programma letteralmente ogni secondo vedo che N cambia crescendo in maniera costante( es 130 134 138) e non potrà mai generare un numero più piccolo della volta precedente fino a quando non supera il range( infatti quando supera 199 riparte da 101). Ovviamente questa cosa la si può notare solo se si avvia il programma a distanze temporali brevi, quindi era giusto una mia curiosità del perché.

claudio862
"Suwako27":
se avvio il programma letteralmente ogni secondo vedo che N cambia crescendo in maniera costante( es 130 134 138)


Se avvii il programma ogni secondo, stai chiamando srand() ogni secondo, passandogli valore restituito da time(), che spesso (ma non necessariamente) è il numero di secondi dal 1970.
Idealmente dovresti chiamare srand() solo una volta, perché è una funzione completamente deterministica.
Probabilmente srand() inizializza il generatore di numeri casuali con un valore direttamente ottenuto dal parametro che gli passi, che aumenta ogni secondo di tre.

Se non sei legato al C, versioni recenti (di questa decade) di C++ hanno librerie per la generazione di numeri casuali molto più avanzate e robuste (tenendo sempre conto che non supportano la generazione di numeri casuali crittograficamente sicuri).

vict85
Il punto è infatti che inizializzi srand con una funzione "temporale". Per capirci, prova a lanciare questo programma:
#include <stdio.h>
#include <stdlib.h>

int
main( void )
{
    unsigned int const K = 1028453982;
    for ( int i = 0; i != 20; ++i )
    {
        srand( K + i );
        unsigned int a = rand( ) % 100 + 100;
        unsigned int b = rand( ) % 100 + 100;
        unsigned int c = rand( ) % 100 + 100;
        printf( "%u %u %u\n", a, b, c );
    }
}

e vedrai lo stesso risultato (ho usato un numero a caso piuttosto grande).

Suwako27
Molto chiaro il concetto, grazie per la spiegazione! :wink:

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.