2015-05-15 16 views
6

Desidero effettuare un'estrazione di lotteria personalizzata per motivare gli utenti a partecipare a un esperimento online. Le regole sono:Algoritmo della lotteria - PHP - la matematica sembra buona, ma la funzione è valida?

  • 10% per ottenere $ 10
  • 1% di possibilità di ottenere 50 $
  • 0,1% di possibilità di ottenere 500 $

la lotteria è una funzione PHP che ottiene chiamato una volta e restituisce il premio (0, 10, 50 o 500). Ho creato la funzione di seguito, e dopo 70 000 prove le statistiche sono:

  • 9,11% per 10 $
  • 0,91% per 50 $
  • 0,01% per 500 $

Dovrei essere preoccupato dell'algoritmo? C'è un modo migliore per creare una buona distribuzione di possibilità rispetto a mt_rand?

function lottery() { 
    // winnings before extraction 
    $win=0; 

    // choose a winning number between 1 and 10 
    $target=mt_rand(1,10); 

    // make three independent extractions, each with 1/10 probability 
    if (mt_rand(1,10) == $target) { 
    // if first extraction is the winning number -> prize=10 
    // probability: 1/10 
    $win=10; 

    if (mt_rand(1,10) == $target) { 
     // if second extraction is ALSO the winning number -> prize=50 
     // probability: 1/10 * 1/10 
     $win=50; 

     if (mt_rand(1,10) == $target) { 
      // if third extraction is ALSO the winning number -> prize=500 
      // probability: 1/10 * 1/10 * 1/10 
      $win=500; 
     } 
    } 
    } 
    // return the prize 
    return $win; 
} 

Grazie per l'aiuto a un principiante!

+1

Se si guardano le 10 $ prezzi poi la deviazione dalla media è di 0.89 che è molto più della deviazione standard per esso (sqrt (0.1 * 0.9)/sqrt (70000) ~ = 0.0011). Quindi qualcosa è (molto probabilmente) andando storto qui, anche se non sono in grado di individuarlo. – vib

+1

A proposito, il valore obiettivo non deve essere casuale. Anche il test '10 * mt_rand()

+0

Un altro modo è disegnare nell'intervallo '(0,999)' e controllare '0 -', '00-' o '000'. –

risposta

2

si dispone di quattro risultati, date le probabilità:

  • 0,1% di probabilità di vincere 500 $.
  • Probabilità dell'1% di vincere $ 500.
  • Probabilità del 10% di vincere $ 500.

Il quarto risultato - nessuna vincita - è del 100% meno la somma degli altri tre risultati, ossia l'88,9%.

Mark Gabriel ha spiegato perché il tuo codice iniziale era disattivato: promuovendo il 10% delle persone che hanno vinto vincitori da $ 10 a $ 50, li porti via dal pool di $ 10 vincitore, che sarà solo il 9% di tutte le persone .

Pham Trung ha contribuito con una soluzione che porta i vincitori di importi più elevati dal pool di non vincitori finora e adatta le probabilità. Questa è una soluzione praticabile, ma la soluzione più semplice è nel mio parere di chiamare il generatore di numeri casuali solo una volta.

Questa soluzione riflette anche l'analogia del biglietto migliore: si collocano 10.000 biglietti in una scatola. I 1.000 biglietti da 1 a 1000 vincono $ 10. I 100 biglietti da 1001 a 1100 vincono $ 50. I dieci biglietti dal 1101 al 1110 vincono $ 500. Tutti i 8890 biglietti da 1111 a non vincono nulla:

function lottery() { 
    var pick = Math.floor(10000 * Math.random()); 
       // random number in the range [0, 10000). 

    if (pick < 1000) return 10; 
    if (pick < 1100) return 50; 
    if (pick < 1110) return 500; 

    return 0; 
} 

In questo codice, i biglietti hanno solo il loro numero scritto su di loro. Ne scegli uno. Quindi verifichi se il numero del biglietto è idoneo per $ 10. In caso contrario, controlli lo stesso biglietto se può scommettere una vincita di $ 50. C'è davvero solo una azione casuale coinvolta.

(ho usato una funzione di numeri casuali in base zero in Javascript invece di PHP di mt_rand, ma credo che la soluzione è limpida.)

+0

Grazie! Ho sottovalutato questo problema. Mark Gabriel ha chiaramente indicato il difetto, ma tu hai - a mio avviso - la soluzione più semplice. Ho modificato il codice in PHP e ottenuto questi risultati per 100000 simulazioni: (10 $ = 10.084; 50 $ = 1.015; 500 $ = 0.1) (10 $ = 9.901; 50 $ = 1; 500 $ = 0.099). Vado con la tua soluzione. – verjas

12

Questo perché le vere probabilità di ottenere ogni nel codice sono:

$ 10 - 0.1*0.9 = 9%

$ 50 - 0.1*0.1*0.9 = 0,9%

$ 500 - 0.1*0.1*0.1 = 0.1%


Questo non è a causa di mt_rand(). Questo è solo un problema di statistiche. Prova a eseguire più iterazioni e vedrai i numeri convergere nei numeri sopra.

Come puoi vedere con i calcoli di cui sopra, non ottieni $ 10 per averlo fatto bene la prima volta, ottieni $ 10 facendolo correttamente la prima volta (10%), e sbagliando la seconda volta (90%).

Seguendo questa logica, è possibile estendere la stessa matematica per $ 50 (ottenendo giusto le prime due volte, 10% e 10%, POI sbagliare la terza volta, 90%), e per $ 500 (si ottiene il trapano).

Con il codice specifico, i calcoli per la probabilità reale sono come sopra.


Vedere il codice nella risposta accettata per il codice corretto con probabilità accurate.

+0

La spiegazione sarebbe la benvenuta. –

+0

Perché il downvote? Questa è matematica, ragazzi. -- Oops scusa. @YvesDao, ero in procinto di modificare la risposta. –

+0

Sì, scaricalo ora, con le migliori quotazioni, ben fatto! –

Problemi correlati