[C] Generatore di numeri casuali con probabilità

bad.alex
Ciao ragazzi.

Volevo chiedervi se sia possibile generare due valori random, la cui probabilità associata è rispettivamente uguale a 60 % e 30% e 10%.
Vi faccio un esempio: ho la possibilità di generare casualmente due valori, 0 e 1. Le possibili combinazioni sono:

1 1
0 0
1 0 (o equivalentemente 0 1)

Ciò che vorrei fare è ottenere che esca 1 1 (immaginate due monete lanciate il cui risultato sia testa (1) testa (1), oppure croce (0) croce (0), testa (1) croce (0)) nel 60% di volte, 1 0 nel 30% e 0 0 nel restante 10 %.


E' possibile realizzare questo procedimento ( in realtà la difficoltà sta nel capire come associare una probabilità di uscita del 60%, 30 % e 10 % ad ognuno dei lanci) in C? Qualora lo fosse, potreste darmi qualche dritta su come procedere?

Vi ringrazio sin da ora per le vostre risposte.

Alex

Risposte
niccoset
Tempo fa avevo un problema simile e lo risolsi in questo modo:

per prima cosa devi generare un numero casuale $ p in [0,1] $, successivamente controlli il valore di $ p $.
Se $ p in [0,0.6] $ sei nel caso $ 1 , 1 $ , se $ p in [0.6,0.9] $ sei nel caso $ 1,0 $ altrimenti ricadi nell'ultimo caso $ 0,0 $.

Spero di esserti stato di aiuto.

apatriarca
Supponiamo di generare un valore uniforme \(\epsilon\) in \([0, 1)\) (o \([0, 100)\) o altro). Se vuoi che qualcosa avvenga con probabilità \(X\) è sufficiente farlo avvenire nel caso in cui \(\epsilon < X\). Supponiamo per comodità di avere una funzione \(drand\) che restituisce un valore double in \([0, 1)\). Il codice per calcolare i tre dadi sarebbe il seguente:
double probs[3] = { 0.6, 0.3, 0.1 };
int dadi[3];
for (int i = 0; i < 3; ++i) {
    double epsilon = drand();
    dadi[i] = epsilon < probs[i];
}

apatriarca
Avevo letto male.. Ma in realtà le tue probabilità non hanno senso.

bad.alex
Grazie mille ad entrambi, niccoset e apatriarca.
Posso chiederti, apatriarca, perché potrebbero non aver senso?

apatriarca
Non hanno senso perché gli stessi simboli appaiono diverse volte nella tua descrizione con probabilità diverse. Non è poi chiaro se l'ordine dei due valori conta o è ininfluente.

vict85
Consideriamo due monete. Le possiamo descrivere con due variabili Bernulliane indipendenti, diciamo \(X = \mathcal{B}(p)\) e \(Y=\mathcal{B}(q)\). Ora tu vuoi trovare i valori di p e q tali per cui \(\mathbb{P}(X=Y=1)=0.6\) e \(\mathbb{P}(X=Y=0)=0.1\) (la terza condizione non aggiunge nulla a queste due essendo l'evento complementare all'unione di questi due eventi indipendenti).

Pertanto si ha che \(pq = 0.6\) e \((1-p)(1-q) = 0.1\). Ovvero \begin{align*} (1-p)(1-q) &= 0.1 \\ 1-q-p+pq &= 0.1 \\ 0.9 + pq &= p+q\,, \end{align*} che diventa \(p+q = 1.5\) sostituendo \(pq\) dalla prima equazione nella seconda.

Siccome \(\displaystyle p = \frac{0.6}{q} \), si ricava \(\displaystyle \frac{6}{10 q} + q = \frac{15}{10} \). Raccogliendo a fattore comune ed eliminando il denominatore (\(q\) è senz'altro diverso da \(0\)), si ricava \(\displaystyle 10 q^2 - 15q + 6 = 0 \).

Siccome \(\Delta = b^2 - 4ac = 15^2 - 4\cdot 10 \cdot 6 = 225 - 240 = - 15 < 0\), non esistono \(p\) e \(q\) che soddisfano il sistema.

In altre parole, indipendentemente dal mezzo, non è possibile generare questa probabilità congiunta tramite l'uso di due variabili bernulliane indipendenti.

apatriarca
A quanto pare ero completamente fuori di testa ieri e non ero in grado di leggere. :( La probabilità ha senso anche se ovviamente le due monete non sono indipendenti tra di loro. La soluzione è quella fornita da @niccoset.

In alternativa puoi trattare le due probabilità separatamente, ma il calcolo delle probabilità è più complicato. Le monete non sono infatti indipendenti ed è quindi necessario fare ricorso a probabilità condizionate. La soluzione più semplice è quella di calcolare le due monete insieme come mostrato in precedenza da @niccoset.

bad.alex
Grazie mille, ragazzi. Il vostro aiuto e i vostri chiarimenti sono sempre preziosi per me!

p.s. Scusate per il ritardo della risposta

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.