Numeri pseudocasuali

di il
3 risposte

Numeri pseudocasuali

Buongiorno, ho creato un programma che dovrebbe restituire numeri pseudocasuali, in un caso con massimo 1, nell'altro con massimo 2.6.
Però mi esce sempre la sequenza 1,0,1,0,1,0... per il numero con max = 1 ho usato rand()%2 (quello che voglio è un float, forse così non va bene?), per l'altro ho usato (rand()/RAND_MAX)*(2.6).
Cosa sbaglio?
Grazie.

3 Risposte

  • Re: Numeri pseudocasuali

    ATTENTO alle regole di conversione, al significato drgli operatori, e al TIPO di numero (float/double CONTRO short/int/long/int8/int16/int32/in64/...)
  • Re: Numeri pseudocasuali

    A mio parere ti sfugge il funzionamento della divisione intera, ecco qualche esempio: 7 / 2 = 2, 7 / 3 = 2, 8 / 3 = 2, cioè sono divisioni INTERE, cioè i decimali vengono buttati via (non sono nemmeno calcolati), è come fare una divisione in colonna tipo alle elementari, se ben ricordo, calcoli solo la parte intera (e poi il resto, ma dettagli). Inoltre, rand() restituisce un intero casuale, quindi rand()%2 anche. E rand()/RAND_MAX (anche RAND_MAX è intero) ti dà 0 se rand()<RAND_MAX o 1 se rand() == RAND_MAX (come suggerisce il nome, RAND_MAX è il massimo valore che restituisce rand()). Se invece aggiungi un cast tutto si risolve
    
    double a = rand()/RAND_MAX; //0.0 o 1.0
    double b = (double)rand()/RAND_MAX; //numero casuale tra 0.0 e 1.0
    
    N.B. il cast ha un alta priorità (a livello di operatori), quindi come l'ho scritto io il cast va subito al valore di ritorno di rand, quindi il compilatore automaticamente converte anche RAND_MAX in double per effettuare la divisione
  • Re: Numeri pseudocasuali

    Innanzitutto hai inizializzato il seme del generatore di numeri casuali richiamando la funzione srand()?

    Iniziamo a considerare
    rand()%2
    L'operatore % necessita che il left-operand (rand() in questo caso) e il right-operand (2 in questo caso) siano degli interi (la condizione è rispettata poichè la funzione rand() ritorna un intero). Ovviamente anche il risultato dell'operazione è un intero, quindi non potrai mai ottenere un float.
    Il risultato di quell'operazione sarà semplicemente 0 se rand() è pari o 1 se rand() è dispari.

    Consideriamo ora
    (rand()/RAND_MAX)*(2.6)
    Dal punto di vista logico ci siamo, nel senso che rand()/RAND_MAX dovrebbe restituire un numero compreso tra 0 e 1 e moltiplicandolo per un generico n si ottiene un numero appartenente all'intervallo [0;n].
    Il problema è che in C/C++ la divisione restituisce risultati diversi a seconda del tipo degli operandi (dividendo e divisore). Possiamo dire che esiste una divisione intera (per cui 7/2=3) e una divisione non intera (per cui 7/2=3.5). Il quoziente viene valutato come divisione intera se entrambi gli operatori sono interi, e come divisione non intera se ALMENO uno dei due operandi è in virgola mobile (float, double, ...).
    Tornando al caso in esame, essendo rand() e RAND_MAX due interi, il quoziente di rand()/RAND_MAX sarà 0 (molto probabilmente) o 1 (se rand()=RAND_MAX, ma la probabilità è di 1/(RAND_MAX+1) ). Se vuoi che il quoziente non venga calcolato come divisione intera devi convertire almeno uno dei due operandi in float/double.
    Ciò può essere fatto in due modi (ipotizziamo che n sia una variabile di tipo double/float):

    - attraverso casting esplicito, cioè (float)rand()/rand_MAX*n (o equivalentemente rand()/(float)rand_MAX*n);

    - oppure scrivendo n*rand()/rand_MAX. In questo caso viene svolto prima il prodotto n*rand() che restituirà un risultato di tipo float, infatti nel momento in cui viene svolta un'operazione (+, -, *, /) tra tipi nativi diversi, l'operando col tipo più "semplice" viene convertito automaticamente (casting implicito) nel tipo dell'altro operando più "complesso" (questo è il motivo per cui n*rand() restituisce un float e per cui in una divisione basta che solo uno dei due operandi sia di tipo float affinchè anche il quoziente sia di tipo float).
Devi accedere o registrarti per scrivere nel forum
3 risposte