[PHP]1x per 20x opvragen uitvoeren

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Tjolk
  • Registratie: Juni 2007
  • Laatst online: 16:29
Ik heb een CSS-popupje met een korte vragenlijst voor mijn bezoekers die nu iedere keer opkomt als aan bepaalde voorwaarden (reeds ingevuld, minder 2 weken geleden al getoond, etc) wel of niet voldaan wordt. Ten behoeve van gebruikersvriendelijkheid en omdat voor een representatieve vragenlijst een populatie van 1 op 20 voldoende is, wil ik het popupje slechts 1x tonen per 20x dat aan de eerdere voorwaarden voldaan is.

Ik zit nu een beetje te denken over wat een efficiente én eerlijke methode is. Met mt_rand(1,20); kan je natuurlijk een eind komen, maar is dat nu echt eerlijk? Een korte proef:
PHP:
1
2
3
for($i = 0; $i < 100; $i++){
    echo mt_rand(1, 20)."<br>";
}

Ik zou willen dat hier alle getallen 5x voorkomen. Dit is absoluut niet het geval, de ene keer zijn het er misschien 1 of 2, de andere keer 8 of 9. Nu is het een drukke site (rond de 1000 unieke bezoekers per dag) dus dat vlakt de boel behoorlijk uit, maar is mt_rand() nu een eerlijke selectiemethode? Uit de documentatie krijg ik het niet helder naar boven. Er wordt verwezen naar Mersenne Twister maar nog steeds is het me niet helemaal duidelijk.


Ik kan natuurlijk in de database steeds een auto_increment cijfer wegschrijven en als dat cijfer deelbaar door 20 is, de vragenlijst tonen (en anders dus niet), maar dat lijkt me overdreven.

Tjolk is lekker. overal en altijd.


Acties:
  • 0 Henk 'm!

  • armageddon_2k1
  • Registratie: September 2001
  • Laatst online: 27-07 10:18
Ger schreef op vrijdag 27 november 2009 @ 14:43:
Ik zou willen dat hier alle getallen 5x voorkomen. Dit is absoluut niet het geval, de ene keer zijn het er misschien 1 of 2, de andere keer 8 of 9.
Even snel sommetje: (1+9) / 2 =5 en (2+8) / 2 = 5. 2x 100 steekproeven is niet representatief. Doe eens 10 000 steekproeven. En dan zal je sneller goed uitkomen. Of beter: 20 * 500 steekproeven. Zal je zien dat het naar een normaal-verdeling gaat toch?

Engineering is like Tetris. Succes disappears and errors accumulate.


Acties:
  • 0 Henk 'm!

  • HuHu
  • Registratie: Maart 2005
  • Niet online
Hoeveel unieke bezoekers heb je in die 2 weken? Want met 1.000 bezoekers en 1-op-de-20 weergaven, heb je op één dag slechts 50 enquête-weergaven. Daarvan gaat 95% hem wegklikken, waardoor op je 2 ingevulde enquêtes komt.

Ik zou hem gewoon tonen aan elke bezoeker, met inachtneming van je eerdere voorwaarden.

Acties:
  • 0 Henk 'm!

  • Tjolk
  • Registratie: Juni 2007
  • Laatst online: 16:29
@armageddon_2k1: Klopt, zover was ik ook. Maar 10000 steekproeven handmatig nalopen vond ik een beetje teveel neigen naar monikkenwerk, een paar collega's vragen is dan prettiger. :)

Ik begrijp dus dat de mt_rand() dus wel een goede oplossing is volgens jou?

[ Voor 3% gewijzigd door Tjolk op 27-11-2009 15:01 ]

Tjolk is lekker. overal en altijd.


Acties:
  • 0 Henk 'm!

  • Tjolk
  • Registratie: Juni 2007
  • Laatst online: 16:29
HuHu schreef op vrijdag 27 november 2009 @ 15:00:
Daarvan gaat 95% hem wegklikken, waardoor op je 2 ingevulde enquêtes komt.
Had ik eerst ook verwacht, maar binnen een dag waren er al ruim 400 die het hadden ingevuld. Het is ook heel bewust een kort simpel "4-klikken-en-klaar" lijstje.

Misschien is 1 op 20 een beetje fanatieke schifting, maar aan iedereen tonen vind ik echt overdreven.

[ Voor 13% gewijzigd door Tjolk op 27-11-2009 15:04 ]

Tjolk is lekker. overal en altijd.


Acties:
  • 0 Henk 'm!

  • HuHu
  • Registratie: Maart 2005
  • Niet online
:D.

Je zit hier in PRG hè. Die 10.000 steekproeven ga je natuurlijk automatisch analyseren.

Acties:
  • 0 Henk 'm!

  • YakuzA
  • Registratie: Maart 2001
  • Niet online

YakuzA

Wat denk je nou zelluf hey :X

analyseren is bijna een groot woord hiervoor:

20 integers waarvan je er random 1 ophoogd.
en aan het eind (na 500/1000/10000/100000x Rand) de 20 integers laten zien.

(iets makkelijker dan een vet lange lijst eruit gooien en dan handmatig optellen ;))

Death smiles at us all, all a man can do is smile back.
PSN


Acties:
  • 0 Henk 'm!

  • Tjolk
  • Registratie: Juni 2007
  • Laatst online: 16:29
Ach ja, dat kan natuurlijk ook. Ik heb het getest door 50 * 20000 waarden te laten genereren. En daarbij ontdek ik overigens iets opvallends: rand() is nauwkeuriger dan mt_rand();
Met rand() heb ik een afwijking die gemiddeld op 0,3% ligt terwijl mt_rand() een afwijking van ongeveer 1% geeft. En dat terwijl volgens de documentatie mt_rand() nauwkeuriger zou moeten zijn!

Dit is de functie die ik gebruikt heb:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
for($x=0; $x<50; $x++) {
    for($i=0; $i<20000; $i++) {
        $a []=rand(1, 20);
    }
    foreach ($a as $waarde) {
        if ($waarde == 20) {
            $b[]=$waarde;
        }
    }   
    $c[] = count($b);
    unset ($a, $b, $i);
}
echo "Aantal keer waarde 20 per 20000: ";
foreach ($c as $result) {
    echo $result.", ";
    $totaal += $result;
}
$gemiddeld = $totaal / 50;
$afwijking = 1000 - $gemiddeld;
$percentage = abs($afwijking / 10) ;
echo "<br>
Gemiddelde afwijking: $percentage%";

Dat spuugt iets uit als:
code:
1
2
Aantal keer waarde 20 per 20000: 1000, 965, 1003, 1027, 1043, 1017, 1017, 1008, 980, 972, 1016, 1024, 1006, 988, 1014, 1011, 996, 979, 1045, 928, 1026, 970, 1012, 981, 1007, 967, 981, 957, 972, 1006, 1000, 1018, 990, 993, 1047, 1060, 985, 993, 1035, 1025, 1057, 994, 1039, 989, 1005, 1035, 983, 975, 970, 999, 
Gemiddelde afwijking: 0.22%

Tjolk is lekker. overal en altijd.


Acties:
  • 0 Henk 'm!

  • eamelink
  • Registratie: Juni 2001
  • Niet online

eamelink

Droptikkels

Ger schreef op maandag 30 november 2009 @ 14:28:
Met rand() heb ik een afwijking die gemiddeld op 0,3% ligt terwijl mt_rand() een afwijking van ongeveer 1% geeft. En dat terwijl volgens de documentatie mt_rand() nauwkeuriger zou moeten zijn!
Uniformiteit is natuurlijk niet de enige eigenschap waar je een RNG op kunt beoordelen. Een RNG die gewoon 1,2,3,4,... genereert en dan modulus 20 scoort bijzonder goed op de uniformiteitstoets, maar is toch een vrij waardeloze random generator voor de meeste toepassingen (al zou hij voor jouw toepassing weer perfect zijn, jij bent immers alléén op zoek naar uniformiteit :))

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Bovendien zegt die afwijking nog niets. Als het echt random is is er ook een kans dat je 10.000 keer hetzelfde getal eruit krijgt. Granted, die kans is heel klein, maar niet nonexistent.

Of zoals Scott Adams ooit tekende:
Afbeeldingslocatie: http://inquietudes.files.wordpress.com/2008/02/dilbert-random.gif

[ Voor 11% gewijzigd door .oisyn op 30-11-2009 14:55 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
.oisyn schreef op maandag 30 november 2009 @ 14:54:
Bovendien zegt die afwijking nog niets. Als het echt random is is er ook een kans dat je 10.000 keer hetzelfde getal eruit krijgt. Granted, die kans is heel klein, maar niet nonexistent.

Of zoals Scott Adams ooit tekende:
[afbeelding]
offtopic:
En de XKCD implementatie die hier bij hoort :+ ( Waar 9 alleen niet aan de RFC voldoet, en er dus 4 gekozen is ;) )
RFC 1149.5 specifies 4 as the standard IEEE-vetted random number.

[ Voor 14% gewijzigd door Woy op 30-11-2009 15:09 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • CyberSnooP
  • Registratie: Augustus 2000
  • Laatst online: 16-08 06:44

CyberSnooP

^^^^ schrijft --->

Bonuspunten voor de title in je plaatje Woy :)

|_____vakje______|


Acties:
  • 0 Henk 'm!

  • denyos
  • Registratie: Februari 2004
  • Laatst online: 21:26
offtopic:
Dat staat al standaard op het plaatje bij xkcd wat gelinked is

Strava


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Om maar weer even on-topic te gaan:

Is het echt belangrijk dat het 100% eerlijk is? Zo te zien is het gewoon de bedoeling om niet elke user een enquette te tonen, en dan is mt_random en gewoon random waarschijnlijk ook wel echt wel "eerlijk" genoeg. Op de lange termijn zul je echt wel ongeveer 1 op de 20 mensen een enquette tonen.

Beide methoden zijn goed genoeg voor normale doeleinden. Voor dingen als encryptie of "zware statistiek" is het natuurlijk wel meer van belang om te kijken wat het daadwerkelijke algoritme is. Echter zal de keuze van de users om de enquette wel of niet in te vullen hier waarschijnlijk al vele malen meer verstoring geven.

[ Voor 32% gewijzigd door Woy op 30-11-2009 15:50 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • sariel
  • Registratie: Mei 2004
  • Laatst online: 22-05-2024
Wat je ook kan doen is een simpel tellertje maken. heb je meteen stats van aantal bezoeken.

if teller % 20 == 0, laat popup zien

[ Voor 18% gewijzigd door sariel op 30-11-2009 16:12 ]

Copy.com


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
sariel schreef op maandag 30 november 2009 @ 16:11:
Wat je ook kan doen is een simpel tellertje maken. heb je meteen stats van aantal bezoeken.

if teller % 20 == 0, laat popup zien
Dat is echter niet zo "eenvoudig". Er is in PHP zover als ik weet standaard niet iets als een application scope beschikbaar. Dan zal je het dus via shared memory, files of een DB moeten doen. Je zult dan echter ook moeten locken/synchroniseren tussen verschillende gelijktijdige requests.

Met een DB en een auto increment is dat natuurlijk wel weer makkelijk te doen, echter is dat weer iets wat de TS juist niet wilde
Ik kan natuurlijk in de database steeds een auto_increment cijfer wegschrijven en als dat cijfer deelbaar door 20 is, de vragenlijst tonen (en anders dus niet), maar dat lijkt me overdreven.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Pfff lekker moeilijk doen allemaal. Of je toont iedereen bij zijn 1e hit dat popupje, of je doet lekker iets met mt_rand(). Het getal 20 is ook volledig uit de lucht gegrepen, dus lekker spannend als het uiteindelijk 1 op de 19 getoond zou zijn. :z

{signature}


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Overigens
eamelink schreef op maandag 30 november 2009 @ 14:34:
[...]

Uniformiteit is natuurlijk niet de enige eigenschap waar je een RNG op kunt beoordelen. Een RNG die gewoon 1,2,3,4,... genereert en dan modulus 20 scoort bijzonder goed op de uniformiteitstoets
Het probleem is dat PRNGs eindig zijn. Modulo 20 geeft per definitie dus al geen uniforme distributie als het aantal mogelijke outputs van de PRNG geen veelvoud is van 20. Oftewel, het pigeonhole principle. En dat is (helaas) precies wat rand(min, max) en mt_rand(min, max) doen, ipv waarden te discarden die niet te distribueren zijn.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#define RAND_RANGE(__n, __min, __max, __tmax) \
    (__n) = (__min) + (long) ((double) ( (double) (__max) - (__min) + 1.0) * ((__n) / ((__tmax) + 1.0)))

PHP_FUNCTION(rand)
{
    long min;
    long max;
    long number;
    int  argc = ZEND_NUM_ARGS();

    if (argc != 0 && zend_parse_parameters(argc TSRMLS_CC, "ll", &min, &max) == FAILURE)
        return;

    number = php_rand(TSRMLS_C);
    if (argc == 2) {
        RAND_RANGE(number, min, max, PHP_RAND_MAX);
    }

    RETURN_LONG(number);
}

Goed, weliswaar geen modulo maar een (langzamere :/) deling via een double. Het principe blijft hetzelfde.

Een andere issue is dat PHP's rand() direct gebaseerd is op de rand() van de onderliggende standaard C library. De eigenschappen van die functie is dus nogal implementatie-afhankelijk. mt_rand() is wel overal hetzelfde.

.edit: oh wacht, ik ben een comment vergeten
C++:
1
2
3
4
5
/*
 * A bit of tricky math here.  We want to avoid using a modulus because
 * that simply tosses the high-order bits and might skew the distribution
 * of random values over the range.  Instead we map the range directly.
 */    

Ja, dorks, in plaats van dat je de hoge bits weggooit gooi je nu de lage bits weg, maw het probleem dat opgelost moet worden wordt er niet mee opgelost |:(

[ Voor 23% gewijzigd door .oisyn op 30-11-2009 16:45 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Tjolk
  • Registratie: Juni 2007
  • Laatst online: 16:29
@voutloos: Klopt, héél spannend is het niet, maar mijn vraag ontstond meer doordat ik me afvroeg of random überhaupt enigszins een gelijke verdeling geeft. Dat doet het dus. En als goede nerd ga ik daar natuurlijk weer véél te ver op in. :P

Tjolk is lekker. overal en altijd.


Acties:
  • 0 Henk 'm!

  • Zeebonk
  • Registratie: Augustus 2005
  • Laatst online: 30-07 20:50
Voutloos schreef op maandag 30 november 2009 @ 16:26:
Pfff lekker moeilijk doen allemaal. Of je toont iedereen bij zijn 1e hit dat popupje, of je doet lekker iets met mt_rand(). Het getal 20 is ook volledig uit de lucht gegrepen, dus lekker spannend als het uiteindelijk 1 op de 19 getoond zou zijn. :z
Misschien makkelijk, maar mensen die voor het eerst een site bezoeken en meteen een vragenlijst over de site krijgen zullen niet echt nuttige feed-back kunnen geven.

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Zeebonk schreef op maandag 30 november 2009 @ 16:44:
[...]


Misschien makkelijk, maar mensen die voor het eerst een site bezoeken en meteen een vragenlijst over de site krijgen zullen niet echt nuttige feed-back kunnen geven.
Maar dat is weer een compleet andere criteria die je met een rand/teller ook niet oplost.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Tjolk
  • Registratie: Juni 2007
  • Laatst online: 16:29
Andere criteria worden hiervoor al afgehandeld, dit criterium heb ik even geïsoleerd voor dit topic.

Overigens is mijn initiele topicvraag meer dan beantwoord, de rest is puur hobbiën. :)

Tjolk is lekker. overal en altijd.


Acties:
  • 0 Henk 'm!

  • creator1988
  • Registratie: Januari 2007
  • Laatst online: 20:55
Desondanks, 1000 bezoekers per dag is dermate weinig dat je weinig problemen gaat ondervinden mbt locking wanneer je de count ergens gaat bijhouden.
Pagina: 1