2009-03-18 19 views
8

Voglio eseguire una funzione che ha 2 risultati diversi, ma voglio che ogni risultato sia veramente del 50%. Sto assumendo che rand (0,1) sia la strada da percorrere, ma sono curioso di sapere se ciò potrebbe favorire l'uno rispetto all'altro. Qual è il modo migliore per ottenere un risultato 50/50?PHP rand() ... ottieni risultati 50/50 veri?

Grazie.

EDIT: grazie ragazzi non voglio che sia casuale, voglio che il risultato sia 101010101 non 111001101. Forse dovrei semplicemente aggiornare un database con l'ultimo valore in uscita e quindi restituire il contrario?

EDIT2: OK Mi dispiace il mio ultimo montaggio è stato fuorviante. Sto solo chiamando la funzione una volta per utente e assegnando quel valore come cookie all'utente. Voglio che ogni utente che visita visualizzi 1 o 0 nell'ordine 1010101.

+1

Allora non è un capovolgimento! : P –

+0

Il mio post ne parla brevemente. La casualità reale può favorire casualmente un numero, ma se invece si inizia con un sacco di numeri e li si mescola casualmente, si evita questo problema (e si introducono altri problemi). – Brian

+0

Puoi spiegare la situazione in cui hai bisogno di questo? Potrebbe non richiedere l'intervento del database. –

risposta

2

a seconda del contesto specifico in cui si intende utilizzare questo numero (ad esempio una base per-user, durata di applicazione , ecc.) è possibile memorizzarlo in un certo numero di posizioni, $ _SESSION, un valore del database o se l'ambito copre solo la pagina corrente, quindi è possibile salvarlo direttamente nel codice di quella pagina.

Un modo semplice per commutare il valore è:

$val = 1 - $val; 

Per una chiamata di database:

UPDATE YourTable SET `next_value` = 1 - `next_value` 

ecc ...

+0

Vedi, penso che questa soluzione sia piuttosto fluida ... ma molto meno ovvia in quello che effettivamente fa ... Penso che qualcuno leggerlo si chiederebbe perché diavolo è stato scritto questo codice. E se $ val (o next_value) venissero in qualche modo incasinati, tutto da quel momento in poi sarebbe sbagliato. – Beska

+0

Sì, sarebbe sicuramente meglio racchiudere una funzione ToggleNextValue() o qualcosa del genere, ma è davvero compito dello sviluppatore assicurarsi che non cambi i valori che non ha alcun cambiamento di business. –

1

Secondo the php manual rand (0,1) è la strada da percorrere. Ma tutto dipende da quanto è buono il generatore di numeri casuali.

1

niente è veramente 50/50. Se si desidera 50/50, quindi eseguire la funzione in modo che i primi 5 risultati siano 1 e gli altri 5 siano 2 ecc.

rand è destinato alla generazione di numeri casuali. Ciò significa che può dare 10 volte lo stesso risultato di fila, ma hey è casuale.

29

in PHP mt_rand() è un generatore di numeri casuali migliore

mt_rand(0,1); 

è sufficiente e dovrebbe generare un valore abbastanza buono 50/50.

Citazione su mt_rand:

Molti generatori di numeri casuali di vecchie libc hanno caratteristiche dubbie o sconosciute e sono lenti. Di default, PHP usa il generatore di numeri casuali libc con la funzione rand(). La funzione mt_rand() è una sostituzione drop-in per questo.

Utilizza un generatore di numeri casuali con caratteristiche note utilizzando il »Mersenne Twister, che produrrà numeri casuali quattro volte più velocemente di quanto fornisce la media libc rand().

Bill aveva un buon collegamento per quanto riguarda un esempio visivo. Non so che cosa PHP l'utente doveva lì per PHP, ma da quando ha compreso il codice che ho ospitato sul mio server (Linux con PHP 5.1.6)

10

Risposta alla domanda modificata: Se si desidera mantenere un rapporto esatto del 50%, la casualità è l'ultima cosa che si desidera. Per i tuoi scopi probabilmente vuoi semplicemente assegnare ad ogni nuovo utente (nessun cookie rilevato) un autonumber dal tuo database, quindi dare la pagina a un utente pari di un numero pari e l'utente a numero dispari all'altra (come suggerito da RobS in un commento).

if(($user_id % 2) == 0) 
    // user id is even 
else 
    // user id is odd 

risposta originale: funzione rand PHP() non è particolarmente buona pseudo-generatore di numeri casuali (vedere Simple Visual Example). Suggerirei invece mt_rand().

2

Sia (rand() e mt_rand()) restituiscono un buon 50%/50% di probabilità.

Ecco un esempio:

$array1 = array(0,0); 
$array2 = array(0,0); 

for ($x = 0; $x < 10000; $x++) { 
    $array1[mt_rand(0,1)] ++; 
    $array2[rand(0,1)] ++; 
} 

print_r($array1); 
print_r($array2); 

Risultati:

Array 1 (mt_rand): 
    [0] => 4910 
    [1] => 5090 
Array 2 (rand): 
    [0] => 4970 
    [1] => 5030 

Secondo la richiesta dell'autore, vuole una distribuzione equa. Quindi provare qualcosa del genere:

$digits = 200; 
$array = array_fill(0, $digits/2, 0); 
for ($x = 0; $x < $digits/2; $x++) 
    $array[] = 1; 
shuffle($array); 

Distribuzione equa e sufficientemente casuale. (Suggerito da Brian)

0

La pseudo-casualità non può mai essere vera casualità. Ogni computazione di numeri casuali basati su un seme o con altri mezzi ha un certo livello di pre-determinazione che può o non può emergere in modo ovvio - come i mini-pattern. Il meglio che puoi sperare è quasi 50/50.

1

Disclaimer: Questo è una cosa stupida da fare per il vostro problema particolare, ma se ti ostini a diffidando il generatore di numeri casuali per essere distribuito in modo uniforme ...

L'algoritmo per la generazione classica aa 50/50 risultato quando non ti fidi che il tuo generatore sia equamente distribuito è il seguente algoritmo. Essere consapevoli che questo algoritmo è più previsto per il fissaggio numeri casuali di numeri pseudo casuali e può infatti rendere i risultati mod a base di peggio:

  1. generare due bit casuali A e B.
  2. Se A == B, goto 1
  3. ritorno B

si può anche garantire la parità di distribuzione da parte solo a partire con un sacco di 1 e 0 (equamente distribuiti) e casualmente li mischiare.

0

se si desidera solo alternando 1 e di 0:

$n = 0; 
$myval = ($n==1 ? $n=0 : $n=1); 
0

Se si vuole seriamente per tornare al valore opposto su ogni iterazione ...

function flip() { 
    static $truthiness = false; 
    $truthiness = !$truthiness; 
    return $truthiness; 
} 

che dovrebbe restituire true, false, true, false, true, ecc ...

Naturalmente, questo funziona solo se l'interprete PHP rimane in memoria tra le chiamate.

Inoltre, se non si conosce la parola chiave static, consultare la voce di manuale PHP su variable scope.

+0

Giusto, ma la funzione viene eseguita una sola volta per utente, quando qualcun altro su un altro sistema visita, voglio che ottengano il favore, quando ho detto 10101 intendevo per ogni visitatore. –

+0

Dovrei controllare, ma se si utilizza mod_php o qualcosa come APC, I * think * mantiene variabili statiche tra gli utenti. Non ho modo di testare dove sono ora (usiamo Java/C# qui). – Powerlord

0

Questo 10101010 non è casuale, è uno schema.
risultato = non risulta

0

Questo è in risposta al tuo commento al tuo post originale:

Il vostro obiettivo è quello di vedere quale versione della pagina genera più vendite.

Ha più senso mostrare casualmente ciascuna pagina a un visitatore piuttosto che girare ABABAB per ogni visitatore successivo.

Mentre non riesco a immaginare alcun motivo per sistematico pregiudizio con il metodo, non è possibile escluderlo. (scenario inverosimile: alcuni bot di tracciamento "seguono" gli utenti alla tua pagina, quindi l'utente 1 ottiene A, bot ottiene B, l'utente 2 ottiene A, bot ottiene B, ecc.)

Ottenere una casualità migliore è più ragionevole quando fare uno studio come quello che stai facendo piuttosto che assicurarti che ogni pagina venga visualizzata esattamente il 50% delle volte.

1

RobS ha una buona soluzione nei commenti, in pratica dicendo che ogni utente può ottenere un numero sequenziale, quindi utilizzando quel numero% 2, si ottiene uno 0 o un 1, che determinerà quale pagina servire. Naturalmente, anche questo non è assolutamente garantito per dare esattamente un rapporto 50/50 ... potrebbe essere un numero dispari di persone!

Inoltre, a seconda di come si determinano gli utenti, può valere la pena verificare che non esiste alcun tipo di correlazione che possa dare a un numero sempre maggiore di persone la probabilità di acquistare ... improbabile, ma solo una cosa da tenere a mente.

Esiste una soluzione alternativa per te, in cui non dovresti preoccuparti di strane correlazioni impreviste: in base ai commenti e alla domanda modificata, stai solo cercando di ottenere un confronto di analisi equo tra l'efficacia di due pagine diverse i layout sono, potresti semplicemente dividere le vendite di ogni layout di pagina per il numero di volte in cui è stato distribuito in modo casuale. cioè, usi il tuo generatore di numeri casuali e tenga traccia di quante volte dà 0 per servire la pagina A, e quante volte dà 1 per servire la pagina B.

Supponiamo che tu abbia guadagnato $ 50.000 in vendita a pagina a con 43 colpi, e $ 46.000 vendite a pagina B con 38 colpi, è sufficiente fare la matematica ...

Page A      Page B 

50000      46000 
----- = 1163 $/hit   ----- = 1211 $/hit 
    43       38 

Dare pagina B il leggero vantaggio.