login  Naam:   Wachtwoord: 
Registreer je!
 Forum

PHP Nadenkvraag - Lightweight random

Offline Martijn - 17/09/2012 11:20 (laatste wijziging 17/09/2012 11:22)
Avatar van MartijnCrew PHP Ik heb een situatie waar ik geen oplossing op hoef, deze kan ik prima zelf bedenken.
Het lijkt me een leuk idee om met ervaren en beginnende programmeurs over situaties na te denken


De situatie:
Ik wil op het scherm A óf B hebben staan, volledig random. Wat is de meest lightweight manier die je kunt verzinnen? Je mag uiteraard benchmarken, en als je een idee hebt maar niet weet of dat zou werken, dan kun je dat altijd vragen.

Een voorbeeldje (note: ik weet ook wel hoe ik dit simpeler maak, maar nu is er ruimte voor verbetering )

  1. $i= time();
  2. if($i%2==0){ echo 'a';}
  3. else{ echo 'b';}


edit: Ga uit van een stukje code wat voor 1x, of een miljoen x achter elkaar moet draaien. Elk beetje snelheidwinst maakt dus uit

21 antwoorden

Gesponsorde links
Offline UpLink - 17/09/2012 13:09 (laatste wijziging 17/09/2012 13:10)
Avatar van UpLink ... De oplossing die ik heb is iets langer qua code, maar het resultaat is hetzelfde.

  1. $letters = 'ab';
  2. $lengte = 1;
  3. $resultaat = substr($letters, rand(0, $lengte), 1);
  4. echo $resultaat;


Waarschijnlijk niet de meest effectieve oplossing, but it does the job... ben niet zo'n goeroe qua PHP =p
Offline koosax - 17/09/2012 15:01
Avatar van koosax Lid Ik zou een array maken waarin alle letters gestopt worden, in dit geval dus alleen A en B.
Hierna zou ik de array_rand() functie gebruiken om willekeurig een letter te kiezen.

  1. <?php
  2. $abArray = array('a','b');
  3. $abArrayRandom = $abArray[array_rand($abArray)];
  4. echo $abArrayRandom;
  5. ?>


Op deze manier is het overzichtelijk en is het makkelijk uit te breiden, ook wanneer er in plaats van enkele letters ook hele woorden worden gebruikt.
Offline Martijn - 17/09/2012 15:16
Avatar van Martijn Crew PHP @koosax: Punten voor uitbreidbaarheid, maar voor slechts 2 waardes is dit een beetje overkill. Php gaat niet zo efficient om met arrays, dus zeker op kleine schaal is dit een beetje pricey als je dit een miljoen keer doet.
Je zou ook zo kunnen doen als je in de array shuffle wilt blijft:

  1. $abArray = array('a','b');
  2. echo current( shuffle($abArray) );
Offline Pieter - 17/09/2012 15:19
Avatar van Pieter Gouden medaille

SEO guru
Martijn, het kan nog iets korter, maar ik denk dat je qua snelheid niet meer beter kan met je time() functie. Door === te gebruiken ben je ook sneller dan de ==.

Voor de sport:

  1. $output = (mt_rand(6,7)===6)?'a':'b';
  2. echo $output;

Offline WouterJ - 17/09/2012 20:14 (laatste wijziging 17/09/2012 20:51)
Avatar van WouterJ HTML gevorderde Nu zijn jullie natuurlijk allemaal bloednieuwsgierig naar wat benchmarking, dus heb ik even een testje gemaakt: http://phphulp....itemasters

Pieter is nu dus het snelst, ong. 5% sneller dan Martijn's eerste script, en verbazingwekkend genoeg zorgt of de shuffle of de current functie ervoor dat Martijn's tweede script enorm traag is (in vergelijking met de rest).
---

Ook even eentje bedacht, geen idee of die snel is of niet:
  1. (rand(0, 1) && print 'a') || print 'b';


---
Voor de eerlijkheid heb ik overal zoveel mogelijk whitespace gestript en onnodige variabele (zoals hierboven bij Pieter) weggehaald). Je ziet dan wat grotere verschillen.
Offline UpLink - 17/09/2012 21:17
Avatar van UpLink ... WouterJ,

Als je jouw Benchmark pagina enkele keren na elkaar refreshed krijg je telkens andere resultaten... De ene keer staan sommige scripts in het groen, dan in het rood, dan in het oranje...
Ik heb het gevoel dat dat waarschijnlijk te maken heeft met de verbinding tussen SiMa en jouw hosting?
Offline WouterJ - 17/09/2012 21:32
Avatar van WouterJ HTML gevorderde UpLink, het heeft niks te maken met SiMa. Misschien wel wat met 'mijn' server die her en der wat traagjes loopt. De tool zelf is ook niet echt geweldig meer, ben bezig met een grote update, dus ik zou het vooral gebruiken voor het algemene overzicht.

De kleuren liggen trouwens ook aan het feit dat de tijd zo idioot snel is. 3 microseconde is 3E-9 seconde = .00000003 seconde. Een klein verschilletje in tijd kan dus al oplopen tot grote procentuele verschillen.
Offline vinTage - 17/09/2012 21:37 (laatste wijziging 17/09/2012 21:46)
Avatar van vinTage Nieuw lid Wel moet gezegd worden dat WouterJ's script het meest vaak als snelste uit de bus komt.

edit: voor WouterJ
Volgens mij is mt_rand() sneller dan rand()
Offline Pieter - 17/09/2012 21:49
Avatar van Pieter Gouden medaille

SEO guru
mt_rand is inderdaad sneller, echo is ook sneller dan print.
Offline vinTage - 17/09/2012 21:51 (laatste wijziging 17/09/2012 21:55)
Avatar van vinTage Nieuw lid hmm Pieter, ik denk dat print sneller is 

edit: net wat rond gezocht en ik was fout 
Offline Pieter - 18/09/2012 08:50 (laatste wijziging 18/09/2012 08:53)
Avatar van Pieter Gouden medaille

SEO guru
WouterJ en mij liggen heel erg nauw aan elkaar gewaagd. Kan je het anders niet 1000x laten uitvoeren? Dan zal het al iets betrouwbaarder zijn, niet? Of al de runs die al gelopen hebben opslaan en er een gemiddelde van nemen?

Waarschijnlijk is WouterJ zijn versie dus sneller dan de mijne in dit geval (mt_rand en echo ipv print):
  1. (mt_rand(0, 1) && echo 'a') || echo 'b';
Offline Martijn - 18/09/2012 09:29 (laatste wijziging 18/09/2012 09:33)
Avatar van Martijn Crew PHP @WouterJ: Dat het sloom is weet ik Zoals ik eerder zei, zijn arrays langzaam. Ik bedacht me gisterenavond dat mijne niet sneller is dan die van de reply boven me, omdat ik de hele array shuffle, wat in php een slecht idee is om high performance te doen.

Als we gaan benchmarken, wil ik deze ook wel zien:

  1. echo uniqid()%2===0?'a':'b';

Mijn vorige met time() is trouwens niet random zat ik later te denken, het is zowel te voorspellen (elke oneven secondes is het a) en het is op grote schaal niet random, want als je er 100 p/sec doet, dan krijg je 100x hetzelfde.

uniqid() gat op microtime, dus die kan tot milliseconde.

@de benchmark, leuk idee, maar volgens mij niet echt een benchmark. Allereerst, kun je er de code bij zetten? 'Martijn1' is niet zo duidelijk 
Verder, hoeveel per stukje code doe je? Eigenlijk moet je het minimaal 1000x per stukje code doen. Ja dan wordt je pagina sloom, maar dan krijg je stabielere resultaten die beter kloppen en minder afhankelijk zijn van een server-hikje 

edit2: Wat ik doe met benchmarks (Met grote getallen!) is het opslaan, en opslaan hoe vaak getest, dus hoe meer mensen het bekijken, hoe beter het klopt. Maar het is nu waarschijnlijk neit in een loop, dus de resultaten zijn veel te gevoelig zo 
Offline WouterJ - 18/09/2012 19:14 (laatste wijziging 18/09/2012 19:17)
Avatar van WouterJ HTML gevorderde Pieter, de code van jou klopt niet. Een echo heeft geen return waarde en kan niet in zo'n conditite worden geplaatst. Print daarin tegen geeft altijd 1 terug en kan daarom wel in zo'n conditie geplaatst worden.

@Martijn en Pieter, de repeat staat momenteel op 1000, ik kan hem ook wat hoger zetten als jullie dat willen?

@De brenchmark, de code van PHPbench heb ik op github gezet: https://github.com/WouterJ/PHPbench/
Ik kan wegens wat gebreken de code niet laten zien bij de test, maar de totale code van deze test is ook op github te bekijken: https://github....asters.php
Het idee van opslaan van de gegevens is een goede, ik ga kijken of ik dat in V2.0 van PHPbench kan stoppen!

Hij staat nu op 10.000 en ik rond hem nu niet meer af, je ziet de maximale significantie.

Even voor de duidelijkheid, de code slaat de totale tijd die nodig is om de functie 10.000 keer uit te voeren op. Deze deelt hij door 10.000 om zo de gemiddelde, en vaak meest precieze, tijd te krijgen voor de functie. Die laat hij zien.

@Martijn, ik weet niet wat er mis is met je laatste script. Maar hij gaat wel heel traag... 
Offline UpLink - 18/09/2012 20:27
Avatar van UpLink ... Misschien nog een leuk idee voor de nieuwe SiMa? Een benchmark optie =D
Offline vinTage - 18/09/2012 21:30 (laatste wijziging 18/09/2012 21:31)
Avatar van vinTage Nieuw lid Ergens gelezen dat bitwise random ook weer sneller zou zijn, dus nog eentje die (mss) ook snel(ler) is:

  1. (mt_rand()&1&&print'a')||print'b';
Offline Martijn - 19/09/2012 09:22 (laatste wijziging 19/09/2012 14:28)
Avatar van Martijn Crew PHP Hm, ik vergeet altijd de naam voor %, maar ik was in de veronderstelling dat die wel snel was Ik geloof dat ik wat code anders moet gaan maken 

@UpLink: Het probleem daarvan is dat we dus mensen code op de server moeten laten uitvoeren, en dan kunnen er rare dingen gaan gebeuren. Verder, stel 100 mensen gaan benchmarken, iets zwaarders dan een echo, dan wordt heel SiMa traag 

edit: Met % heet modulus, het kwam opeens tot me 
Offline Sam - 19/09/2012 18:56
Avatar van Sam PHP expert
  1. echo chr(mt_rand(65, 66));
Offline UpLink - 19/09/2012 20:46
Avatar van UpLink ...
Martijn schreef:
Hm, ik vergeet altijd de naam voor %, maar ik was in de veronderstelling dat die wel snel was Ik geloof dat ik wat code anders moet gaan maken 

@UpLink: Het probleem daarvan is dat we dus mensen code op de server moeten laten uitvoeren, en dan kunnen er rare dingen gaan gebeuren. Verder, stel 100 mensen gaan benchmarken, iets zwaarders dan een echo, dan wordt heel SiMa traag 

edit: Met % heet modulus, het kwam opeens tot me 


Ok, let go of my idea then... =p
Had zover nog ni nagedacht =p
Offline Martijn - 20/09/2012 09:23
Avatar van Martijn Crew PHP @Sam: ik zie dat je 66,67 gebruikt, zijn dat a en b? Niet zo praktisch om uit te breiden maar leuk bedacht dan 
Offline Pieter - 21/09/2012 16:13
Avatar van Pieter Gouden medaille

SEO guru
@Sam, leuk, die kende ik niet!
Offline vinTage - 10/10/2012 22:09
Avatar van vinTage Nieuw lid Beetje laat, maar toch noemenswaardig...

Vandaag zat ik wat te prutsen met die 'bitwise' random, maar dat blijkt niet echt zo random te zijn..

Op IRC (ja iedereen denkt mee) hebben ze me wat meer uitleg gegeven...

Voorstelling van het onderwerp:
mt_rand(0, 100) versus mt_rand()&100

Antwoord:
irc schreef:
100 bitwise = 1100100
dus je kan alleen maar een resultaat krijgen wat 11**1** kan zijn
met * = 1 of 0



Wat er dus op neerkomt dat mijn bijdrage aan die benchmark teniet gedaan mag worden, omdat die niet even random is als de andere!
Gesponsorde links
Je moet ingelogd zijn om een reactie te kunnen posten.
Actieve forumberichten
© 2002-2024 Sitemasters.be - Regels - Laadtijd: 0.268s