Pagina 1 di 1

[C] rand() tra zero e uno

Inviato: martedì 6 maggio 2014, 0:30
da m92c
Salve a tutti.
Devo generare dei numeri random compresi tra 0 e 1.
Il codice che ho scritto è il seguente:

Codice: Seleziona tutto

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

int main(){

	int i;
	double num;

	srand(time(NULL));

	
	num=rand()%1;
	for(i=0; i<10; i++){
		printf("%.6f\n", num);
	}

	return 0;
}
Eseguendolo, anche più volte, mi restituisce 10 numeri tutti uguali a 0.000000
Dove sbaglio??
Grazie.

Re: [C] rand() tra zero e uno

Inviato: martedì 6 maggio 2014, 1:07
da vaeVictis
Così al volo questo dovrebbe funzionare. Nel senso che compila, ti risolve un errore e dovrebbe (per questo dicevo "dovrebbe funzionare") anche dare correttamente i numeri (pseudo) casuali tra 0 e 1.
Qui il codice (con un paio di commenti essenziali) e sotto la spiegazione

Codice: Seleziona tutto

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

int main(){

   int i;
   double num;

   srand(time(NULL));

   //~ ERRORE: num lo devi "ritirare" ad ogni iterazione del ciclo for, 
   //~ quindi lo devi spostare al suo interno  
   //~ num=rand();

   //~ Decommenta la riga sotto per stampare il valore di RAND_MAX
  //~ printf("%d\n", RAND_MAX);

   for(i=0; i<10; i++){
	         //~ comando spostato dentro al ciclo for
	         num=rand()/(float)RAND_MAX;
      printf("%.6f\n", num);
   }

   return 0;
}
L'errore è spiegato nel commento interno al codice.
Inoltre, la variabile che stampi

Codice: Seleziona tutto

num=rand()/(float)RAND_MAX
è diversa dalla tua. Devi normalizzare il numero estratto da rand, con il suo massimo RAND_MAX, su cui fai un cast a float per non causare troncamenti a zero.
Per chiudere, il fatto che a te veniva sempre 0 è dovuto, in primo luogo perché fai una singola estrazione prima del ciclo for, ma anche perché l'operazione che hai fatto dà sempre 0 come risultato in quanto il modulo tra il numero 1 e un qualsiasi altro numero intero è 0.

Domani comunque per curiosità controllo se è questo il modo giusto o se devi calcolare num altrimenti.
Ciao.

Re: [C] rand() tra zero e uno

Inviato: martedì 6 maggio 2014, 17:55
da gila75
Ciao m92c.
Io avevo affrontato la cosa tempo fa per una mia esigenza.
Aspetta conferme, ma io avevo risolto così:

Codice: Seleziona tutto

// SEQUENZA RANDOM DI NUMERI FLOAT
//**********************************************
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
   
    

int main(void) 
{

    int rnd;
    float x;
    int i;
    srand((unsigned) time(NULL));
    for (i=0; i<10; i++) 
    {
        rnd=rand()%100;
        x=(float)rnd/100;
        printf ("[%d] [rnd %d] \t %1.2f\n",i,rnd,x);
    }
    return 0; 
}





 
Se ti garba il metodo e non capisci qualcosa, chiedi pure :)
Logicamente il grado di accuratezza 0.1 oppure 0.36 o 0.999 lo stabiliamo noi in fase di compilazione.

Re: [C] rand() tra zero e uno

Inviato: mercoledì 7 maggio 2014, 8:38
da vbextreme
Naturalmente un programmatore potrebbe possedere una libreria con tutte le funzioni matematiche che incontra, tipo:

Codice: Seleziona tutto

void mth_initrandom()
{
    srand((unsigned)time(NULL));
}

double mth_randomf01()
{
    return ((double)(rand()) / ((double)RAND_MAX + 1.0));
}

Re: [C] rand() tra zero e uno

Inviato: mercoledì 7 maggio 2014, 9:22
da vaeVictis
@gila75
A voler essere rigorosi, in questo modo

Codice: Seleziona tutto

        rnd=rand()%100;
        x=(float)rnd/100;
stai viziando la distribuzione, nel senso che i numeri ottenuti con rnd non sono distribuiti in modo equiprobabile tra 0 e 99.
Il motivo è abbastanza ovvio.
Quindi direi che non è un buon modo per estrarli.
Lo puoi verificare tranquillamente con una analisi delle frequenze.

@vbextreme
Non sono del tutto convinto che quel + 1.0

Codice: Seleziona tutto

    return ((double)(rand()) / ((double)RAND_MAX + 1.0));
non possa dar problemi.
Che dici?

Re: [C] rand() tra zero e uno

Inviato: mercoledì 7 maggio 2014, 10:43
da vbextreme
Non sono del tutto convinto che quel + 1.0
Penso che nella comunità ci sia solo una persona che possa rispondere correttamente a questa domanda.

Tutti i libri che ho letto usano quella funzione per estrarre 0-1 o in alternativa metodi decisamente piu contorti e complessi.
Quel piu uno dovrebbe servire per la corretta distribuzione dei numeri pseudo casuali,dovrebbe essere una toppa alla funzione rand().

Re: [C] rand() tra zero e uno

Inviato: mercoledì 7 maggio 2014, 10:55
da vaeVictis
Premetto che quel +1.0 è il motivo per cui nel mio primo messaggio mettevo le mani avanti dicendo che dovevo verificare che quello suggerito (ovvero lo stesso tuo metodo, ma senza quel +1.0) fosse corretto.
Insomma... ero indeciso se mettere o non mettere quel +1.0

Il motivo della perplessità è il seguente.
RAND_MAX è il massimo numero estratto dalla funzione rand().
Aggiungergli 1 può causare un warning ovvio:

Codice: Seleziona tutto

casual.c:16:34: warning: integer overflow in expression [-Woverflow]
Quello che non consideravo, leggendo le varie risorse a riguardo, è che c'è il cast a double e quindi il problema dell'overflow è risolto :)
Pertanto, da questo punto di vista, non rappresenta un problema.

Detto questo, quella divisione non è per via di una toppa di rand :)
Si fa quella divisione per normalizzare il numero estratto, dividendolo per il "numero" di numeri estraibili.
Se tu estrai un numero a caso tra 0 e RAND_MAX hai un totale di RAND_MAX + 1 numeri da poter estrarre.
La cosa simpatica è che sia con il +1 sia senza viene lo stesso risultato :D

Codice: Seleziona tutto

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

int main(){

   int i;
   double num;

   srand(time(NULL));

   
   for(i=0; i<10; i++){
      num = rand();
      printf("%.6f\n", num/(float)RAND_MAX);
      printf("%.6f\n", num/((float)RAND_MAX + 1));
   }

   return 0;
}

Codice: Seleziona tutto

vaevictis@vaevictis-HAL:~/Scrivania$ g++ -o casual casual.c 
vaevictis@vaevictis-HAL:~/Scrivania$ ./casual 
0.103147
0.103147
0.507267
0.507267
0.855904
0.855904
0.928802
0.928802
0.760466
0.760466
0.582616
0.582616
0.916554
0.916554
0.422087
0.422087
0.699902
0.699902
0.297756
0.297756
Tutti questi ragionamenti sono ovviamente da inquadrare in uno scenario in cui rand() non sia da evitare come i vetri nelle mutande.

Re: [C] rand() tra zero e uno

Inviato: mercoledì 7 maggio 2014, 18:46
da gila75
stai viziando la distribuzione, nel senso che i numeri ottenuti con rnd non sono distribuiti in modo equiprobabile tra 0 e 99.
Il motivo è abbastanza ovvio.
Certo Vae...era solo un abbozzo d'idea, uno spunto diciamo :)