|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Member
Iscritto dal: Sep 2009
Messaggi: 41
|
[C] Generare numeri rand con probabilità determinata
Ciao a tutti!! E' da poco che scrivo nel forum. Spero di non sbagliare qualcosa...
Ho un problema con un esercizio in linguaggio C: Dato un vettore di 50 elementi, in ogni elemento deve essere inserito un numero pseudocasualmente estratto tra 1, 2 e 3 con probabilità rispettivamente di 1/5, 2/5, 2/5. Ho studiato sul libro "C Corso completo di programmazione " seconda ed. deitel e non ho mai incontrato esercizi del genere. Se non ci fosse il fattore probabilità sarebbe facilissimo...qualcuno ha idea di come risolverlo??... |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Mar 2002
Città: Chi è nato a Roma è romanista.I laziali so quelli de fori le mura
Messaggi: 1291
|
Mi viene in mente che potresti fargli estrarre un numero a caso tra 1 e 5, poi scrivi così:
if numero estratto è 4 allora numero estratto diventa 2 if numero estratto è 5 allora numero estratto diventa 3 Così avresti 1 possibilità su 5 che esca 1, 2 possibilità su 5 che esca 2 (cioè quando esce 2 o 4) e 2 possibilità su 5 che esca 3 (cioè quando esce 3 o 5)
__________________
--. MARCK77 .-- |
|
|
|
|
|
#3 |
|
Member
Iscritto dal: Apr 2007
Messaggi: 182
|
Oppure sfruttando sempre questa idea in modo più efficiente potresti riempire un vettore di 5 elementi in questo modo:
Codice:
int vet [] = {1,2,2,3,3}
|
|
|
|
|
|
#4 |
|
Member
Iscritto dal: Sep 2009
Messaggi: 41
|
grazie delle risposte
|
|
|
|
|
|
#5 | |
|
Senior Member
Iscritto dal: Apr 2003
Messaggi: 16462
|
Quote:
Allora il problema si riduce a trovare una variable casuale X che prende valori 1,2,3 con probabilita' rispettive di 1/5,2/5 e 2/5. X = 1 se 0<U<1/5 X = 2 se 1/5<U<3/5 X = 3 se 3/5<U<5 Si verifica immediatamente che p(X=1)=1/5, p(X=2)=2/5 e p(X=3)=2/5
__________________
MICROSOFT : Violating your privacy is our priority Ultima modifica di goldorak : 15-12-2010 alle 22:20. |
|
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: Apr 2003
Messaggi: 16462
|
Quote:
La tua soluzione e' concettualmente sbagliata.
__________________
MICROSOFT : Violating your privacy is our priority |
|
|
|
|
|
|
#7 | |
|
Member
Iscritto dal: Sep 2009
Messaggi: 41
|
Quote:
|
|
|
|
|
|
|
#8 | |
|
Senior Member
Iscritto dal: Apr 2003
Messaggi: 16462
|
Quote:
Poi in base al valore di U metti 1 o 2 o 3 nelle posizione corrente nell'array. Per intenderci, generi U e trovi che il suo valore sta tra 0 e 1/5 allora metti 1 nel array. Genera di nuovo U, se trovi che il suo valore sta tra 1/5 e 3/5 allora metti 2 nell'array e cosi' via. In questo modo riempi l'array con 1 o 2 o 3 con le probabilita' giuste. Il modo in cui hai costruito X ti garantisce che 1,2,3 verranno estratte con le probabilita' indicate dal problema.
__________________
MICROSOFT : Violating your privacy is our priority Ultima modifica di goldorak : 16-12-2010 alle 10:00. Motivo: Eliminato la parte sbagliata del ragionamento |
|
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Mar 2002
Città: Chi è nato a Roma è romanista.I laziali so quelli de fori le mura
Messaggi: 1291
|
Cosa non può generare più di 3 elementi? Anche la tua "U" alla fine può avere 5 valori no? Non capisco la differenza tra la tua soluzione e la mia sinceramente. Dove è sbagliata la mia? Grazie mille.
__________________
--. MARCK77 .-- |
|
|
|
|
|
#10 | |
|
Senior Member
Iscritto dal: Mar 2002
Città: Chi è nato a Roma è romanista.I laziali so quelli de fori le mura
Messaggi: 1291
|
Quote:
quindi bisogna fare "rand()%5" per avere un valore tra pseudocasuale tra 0 e 4 in output. Ti risulta? Oltretutto se fosse vero quello che dici moltiplicando la rand() per 5 otterresti solo o 0 o 5, mai un valore intermedio.. Ciao.
__________________
--. MARCK77 .-- Ultima modifica di marck77 : 16-12-2010 alle 08:33. |
|
|
|
|
|
|
#11 |
|
Member
Iscritto dal: Mar 2008
Messaggi: 267
|
E' così, anche se il metodo "rand()%n" genera un numero random usando le cifre meno significative, il modo giusto sarebbe:
Per generare un numero intero tra 0 e n-1 Codice:
rand()*n/(RAND_MAX+1) Codice:
rand()*n/(RAND_MAX+1.0) |
|
|
|
|
|
#12 | ||
|
Senior Member
Iscritto dal: Apr 2003
Messaggi: 16462
|
Quote:
Quote:
Comunque il ragionamento che ho fatto e' corretto. Basta generare un valore casuale (non intero) tra 0 e 5 e poi verificare in che intervallo cade. Sulla base di questo poi fai l'assegnamento nell'array.
__________________
MICROSOFT : Violating your privacy is our priority |
||
|
|
|
|
|
#13 | ||
|
Member
Iscritto dal: Sep 2009
Messaggi: 41
|
Quote:
Quote:
Tuttavia così facendo l'algoritmo non funziona bene. Per tutti gli algoritmi qui proposti ho randomizzando i numeri con srand(time(NULL)) e tutto ok. Ho fatto questo miniprogramma per verificare effettivamente che rand() riuscisse a generare dei numeri con la virgola Codice:
main()
{
double x;
srand(time(NULL));
x = rand()*5/(32767+1.0);
printf("%.10f", x);
}
|
||
|
|
|
|
|
#14 |
|
Member
Iscritto dal: Sep 2009
Messaggi: 41
|
ragazzi ce un altro problema..praticamente la seconda parte del problema chiede di scrivere quel vettore (x[50]) in un file ad accesso casuale
Codice:
#include<stdio.h>
main()
{
int x[50];
int prob[5] = { 1, 2, 2, 3, 3 };
int occorrenze[3] = {0};
int restituzioni[50] = {0};
int i;
FILE *filePtr;
srand(time(NULL));
for ( i = 0; i <= 49; i++ )
{
x[i] = prob[(rand() % 5)]; // --> prob[ 0 <= indice < 5] <--
++occorrenze[x[i]-1];
}
for ( i = 0; i <=2; i++ )
{
printf("Occorrenze di %d: %d\n", i+1 , occorrenze[i]);
}
if ( (filePtr = fopen("vettore.dat", "wb")) == NULL)
{
printf("Errore!! Il file non può essere aperto\n");
}
else
{
for ( i = 0; i < 50; i++ )
{
fseek( filePtr, i * sizeof ( x[i] ), SEEK_SET );
fwrite( &x[i], sizeof ( x[i] ), 1, filePtr);
}
}
/* Verifichiamo che i dati memorizzati sono stati giustamente inseriti*/
for ( i = 0; i < 50; i++ )
{
fread ( &restituzioni[i], sizeof( restituzioni[i] ), 1, filePtr);
printf("%d\n", restituzioni[i]);
}
fclose(filePtr);
}
I dati sono stati memorizzati male nel file oppure sono stati letti scorrettamente...Dov'è che sbaglio??? |
|
|
|
|
|
#15 | |
|
Member
Iscritto dal: Mar 2008
Messaggi: 267
|
Quote:
1) Il seed viene inizializzato con un'unità di tempo precisa al secondo, quindi se tu esegui il programma 2-3 volte in un secondo, il seed sarà sempre uguale. 2) La variazione del seed è minima e viene generato solo un numero, dopodiché il programma viene terminato, rieseguito, ed il seed viene reinizializzato. Se provi con un programma del genere: Codice:
int main()
{
srand((unsigned)time(NULL));
for (int i = 0; i < 100; i++)
{
double x = rand()*5/(32767+1.0);
printf("%.10f ", x);
}
return 0;
}
|
|
|
|
|
|
|
#16 |
|
Senior Member
Iscritto dal: Dec 2007
Città: Palestro
Messaggi: 1960
|
Sinceramente, a me sembra che il ragionamento fatto sia praticamente lo stesso..se porti il tuo "/5" dall'altra parte dell'uguale, ottieni lo stesso calcolo! Anzi, così facendo l'arrangi con un rand()%5 (andando da 0 a 4, invece che da 1 a 5..cambia poco), invece di coinvolgere anche delle moltiplicazioni e divisioni.. Che poi sia più efficiente fare una rand()%4 indicante l'indice dell'array, è fuori discussione!
__________________
My PC: Case: BeQuiet! Pure Base 500 + BeQuiet! Pure Wings 2 140mm & Noctua NF-A14 PWM front intake + BeQuiet! Pure Wings 2 140mm rear exhaust - CPU: AMD Ryzen7 5800X3D (DVID: -0.1V) - CPU Cooler: Noctua NH-D15 - MB: MSI X570 Gaming Edge WiFi - PSU: Corsair RM850 full modular - GPU: Gigabyte 2070 Super Gaming OC 3X (fallata....! |
|
|
|
|
|
#17 | |
|
Senior Member
Iscritto dal: Apr 2010
Città: Frosinone
Messaggi: 416
|
Quote:
Codice:
fwrite(x, sizeof (int), 50, filePtr); Codice:
fseek(filePtr, 0, SEEK_SET); fread(restituzioni, sizeof(int), 50, filePtr); |
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 17:16.




















