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: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
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