Oppure

Loading
10/05/11 17:25
belledetta
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 %???

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

int main(int argc, char *argv[])
{
    int a, b, n, seme;
	
	printf("\ninserisci a = ");	scanf("%d",&a);
	printf("\ninserisci b = ");	scanf("%d",&b);
	printf("\ninserisci n = ");      scanf("%d",&n);
	printf("\ninserisci seme = "); scanf("%d",&seme);
	
		
	srand(seme);
	int num;
	for (int i=0; i<n; i++){
		num = a+rand()*b/RAND_MAX;
		printf("%d\t",num);
		}
			  
	printf("\n");
	return 0;

}



Ultima modifica effettuata da belledetta 10/05/11 17:26
aaa
10/05/11 17:29
pierotofy
Per generare un numero casuale tra a e b (inclusi):

rand() % b + a;


Qual'e' il problema?
Il mio blog: piero.dev
10/05/11 17:35
belledetta
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??
aaa
10/05/11 19:14
pierotofy
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

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


Che e' tuttavia meno efficente di:

rand() % b + a;


La conversione da float a int e' implicita.
Il mio blog: piero.dev
10/05/11 20:41
belledetta
grazie mille:)
aaa
11/05/11 9:14
TheKaneB
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.
aaa
11/05/11 12:20
belledetta
Ben detto theKaneB .... da buon matematico avrei dovuto pensarci a verificare l'algoritmo. Grazie
aaa
11/05/11 16:24
pierotofy
Never mind! Ho interpretato male la documentazione di rand().

Grazie TheKaneB per la correzione.
Ultima modifica effettuata da pierotofy 11/05/11 16:41
Il mio blog: piero.dev