Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - [C]stampa numeri casuali in intervallo
Forum - C/C++ - [C]stampa numeri casuali in intervallo

Avatar
belledetta (Normal User)
Rookie


Messaggi: 25
Iscritto: 07/09/2010

Segnala al moderatore
Postato alle 19:25
Martedì, 10/05/2011
salve sono una dilettante..ho dei problemi con il mio codice in C. ora illustro ciò che dovrei fare: dati in input 4 interi (a,b,N, seme) generare N numeri casuali con seme della rand in input tali che siano compresi tra a e b inclusi.
Il mio codice stampa i numeri fino a b+1. esiste un codice standard che utilizzi una proporzione rispetto a RAND_MAX  e non l'operatore %???

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int main(int argc, char *argv[])
  5. {
  6.     int a, b, n, seme;
  7.        
  8.         printf("\ninserisci a = ");     scanf("%d",&a);
  9.         printf("\ninserisci b = ");     scanf("%d",&b);
  10.         printf("\ninserisci n = ");      scanf("%d",&n);
  11.         printf("\ninserisci seme = "); scanf("%d",&seme);
  12.        
  13.                
  14.         srand(seme);
  15.         int num;
  16.         for (int i=0; i<n; i++){
  17.                 num = a+rand()*b/RAND_MAX;
  18.                 printf("%d\t",num);
  19.                 }
  20.                          
  21.         printf("\n");
  22.         return 0;
  23.  
  24. }





Ultima modifica effettuata da belledetta il 10/05/2011 alle 19:26
PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6108
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 19:29
Martedì, 10/05/2011
Per generare un numero casuale tra a e b (inclusi):

Codice sorgente - presumibilmente Plain Text

  1. rand() % b + a;



Qual'e' il problema?


Seguimi su Twitter: http://www.twitter.com/pierotofy

Fai quello che ti piace, e fallo bene.
PM Quote
Avatar
belledetta (Normal User)
Rookie


Messaggi: 25
Iscritto: 07/09/2010

Segnala al moderatore
Postato alle 19:35
Martedì, 10/05/2011
anche io avevo pensato di fare in questo modo ma il mio prof ci tiene a impostare la proporzione che purtroppo nn ho appuntato a lezione. potrebbe essere

a + (b-a) * rand() / RAND_MAX    ???? non sono sicura che stampi i valori con a compreso.
io penso che in questo modo sia sbagliato anke perchè nn si tratta di operazioni tra interi ma float (io ho bisogno di int )e quindi le approssimaz di macchina possano cambiare un pò l'equiprobabilità dell'uscita dei numeri. o sbaglio??

PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6108
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 21:14
Martedì, 10/05/2011
Ah, il tuo professore e' uno di quelli...

rand() ritorna un numero tra 0 e RAND_MAX.

Quindi:

rand() / RAND_MAX ti ritorna un numero (float) tra 0 e 1. (Chiamalo randomRatio)

Ora il tuo range e' da A a B, ma parte sempre da A.

         --------------
---------------------------------------------------
0       A                B                          RAND_MAX

La differenza tra B e A e' il numero che devi moltiplicare per randomRatio, cosi' avrai un numero compreso tra A e B (relativo ad A) (Chiamalo n).

------------------
A     n              B

Adesso devi solo aggiungere A al risultato.

         --------------
---------------------------------------------------
0       A        n       B                          RAND_MAX

Codice sorgente - presumibilmente Plain Text

  1. num = ((rand() / RAND_MAX) * (b - a)) + a



Che e' tuttavia meno efficente di:

Codice sorgente - presumibilmente Plain Text

  1. rand() % b + a;



La conversione da float a int e' implicita.


Seguimi su Twitter: http://www.twitter.com/pierotofy

Fai quello che ti piace, e fallo bene.
PM Quote
Avatar
belledetta (Normal User)
Rookie


Messaggi: 25
Iscritto: 07/09/2010

Segnala al moderatore
Postato alle 22:41
Martedì, 10/05/2011
grazie mille:)

PM Quote
Avatar
TheKaneB (Member)
Guru^2


Messaggi: 1787
Iscritto: 26/06/2009

Segnala al moderatore
Postato alle 11:14
Mercoledì, 11/05/2011
mh... no piero...

rand() % B
da un risultato compreso tra 0 e B-1

rand() % B + A
da un risultato compreso tra (0+A) e (B-1+A), quindi A <-> B+A-1

che è diverso dall'intervallo cercato.

Dal momento che il range è A <-> B e la sua differenza è B-A, è assolutamente corretto fare

rand() % (B-A)
che da un risultato compreso tra 0 e B-A-1

sommando A
rand() % (B-A) + A
da un risultato compreso tra (0+A) e (B-A-1 + A)
cioè A <-> B-1 +A-A
cioè A <-> B-1

per includere anche B nell'intervallo basta fare rand() % (B-A+1) + A

Il metodo con i float è scorretto per un semplice motivo: come già correttamente intuito da belledetta, le operazioni in floating point creano un "bias" a causa del fatto che la loro precisione diminuisce all'aumentare del range. La precisione massima si ha nell'intorno di 1, e comunque non è un buon metodo per generare distribuzioni di probabilità lineari.

Se proprio vuoi usare una proporzione, consapevole dei difetti prima esposti, la formula corretta è:
double ratio = rand() / (double)RAND_MAX;
double randomNumber = (b-a) * ratio + a;

Ho usato i double perchè offrono 64 bit di precisione, invece di 32 (quindi limitando al minimo il difetto di cui sopra), e nota la divisione che contiene un casting a double, in questo modo impedisco al compilatore di fare una divisione tra interi, che scarterebbe il resto della divisione.


Software Failure: Guru Meditation
Forum su Informatica, Elettronica, Robotica e Tecnologia: http://www.nonsoloamiga.com
PM Quote
Avatar
belledetta (Normal User)
Rookie


Messaggi: 25
Iscritto: 07/09/2010

Segnala al moderatore
Postato alle 14:20
Mercoledì, 11/05/2011
Ben detto theKaneB .... da buon matematico avrei dovuto pensarci a verificare  l'algoritmo. Grazie

PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6108
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 18:24
Mercoledì, 11/05/2011
Never mind! Ho interpretato male la documentazione di rand().

Grazie TheKaneB per la correzione.

Ultima modifica effettuata da pierotofy il 11/05/2011 alle 18:41


Seguimi su Twitter: http://www.twitter.com/pierotofy

Fai quello che ti piace, e fallo bene.
PM Quote
Avatar
TheKaneB (Member)
Guru^2


Messaggi: 1787
Iscritto: 26/06/2009

Segnala al moderatore
Postato alle 23:27
Mercoledì, 11/05/2011
figurati, più teste ragionano meglio di una sola (di solito) :D


Software Failure: Guru Meditation
Forum su Informatica, Elettronica, Robotica e Tecnologia: http://www.nonsoloamiga.com
PM Quote