Portal Home > Knowledgebase > Articles Database > PHP Rand Num Generator (weighted)
PHP Rand Num Generator (weighted)
Posted by Goldfiles, 07-31-2008, 08:45 PM |
Does anyone know how to do this?
I want to randomly pick a number between 1 and 100 using PHP. Easy, but, I want to weight the selection so the lower numbers have a higher probability to show up. Is this possible?
Thanks!
|
Posted by Jatinder, 07-31-2008, 10:02 PM |
Try the following:
If you want to generate a random number between 1 and 100 but want the numbers below 20 to have higher probability, call the function as:
weightedRand(1,100, 20);
You can increase the loop count (currently hard coded to 10) in the function to increase the probability still further. The more loops you have, higher will be the probably of lower number being generated.
|
Posted by BostonGuru, 08-01-2008, 05:50 PM |
Somebody correct me if I am wrong, but I believe if you want a smoothly weighted Generator (such as 5 is slightly heavier than 6, 55 is slightly heavier than 56, etc) then you generate a random number between 1 and e^100, then take the log of that value, and round that result to the nearest int.
EDIT: e^100 is a huge number, but you could get the same result by using e^10, then multiplying the log you get by 10, then rounding.
|
Posted by bigfan, 08-02-2008, 10:13 AM |
I'm sure this solution to the problem (as described by DanCF, i.e. smoothly weighted) can be shown to be mathematically bogus, but it seems to produce pretty good results without using a lot of resources.
Edit: Corrected array_fill() in test code.
Last edited by bigfan; 08-02-2008 at 10:24 AM.
|
Posted by Jatinder, 08-02-2008, 11:28 AM |
I have problem understanding your code especially the while loop.
AFAIK, this while loop will run (loop) only once.
|
Posted by bigfan, 08-02-2008, 11:47 AM |
Thanks, Jatinder, you're right. It was a case of getting it to do what I wanted, then stopping too soon.
The simplified version, with a name change to better reflect what it does:
|
Posted by BostonGuru, 08-02-2008, 12:52 PM |
I think you guys are making this more complicated than it has to be. Just use this:
I ran this 10,000 times, and the results were like so:
01-10 => 4880
11-20 => 1601
21-30 => 876
31-40 => 635
41-50 => 487
51-60 => 415
61-70 => 319
71-80 => 300
81-90 => 248
91-100 => 231
I believe this is the weighting he is looking for.
|
Posted by bigfan, 08-02-2008, 02:53 PM |
I don't know by what measure that can be called less complicated; it's definitely less flexible. But if you mean that it's all on one line, not in a function, hard-coded, and thus simpler, well, there's this:That's also faster by half in my tests and gives these results:
01-10 => 3524
11-20 => 1832
21-30 => 1369
31-40 => 992
41-50 => 753
51-60 => 615
61-70 => 435
71-80 => 267
81-90 => 161
91-100 => 52
Which results are better I guess would depend on the statistical criteria.
|
Posted by BostonGuru, 08-02-2008, 04:22 PM |
What you just wrote would work great as well. I probably should have used mt_rand instead of rand in what I wrote, as it is supposedly 4x faster. As far as complication went, I was referring to the fact that the function listed above had loops in it, etc, which can burn time, and unnecessarily complicate matters. The line of code I wrote just takes a linear output (y=x) and converts it to an exponential output (y=e^x). The reason it looks complicated is because while most languages have a rand function that produces a float between 0 and 1, whereas php only generates integers, and thus needs to first be converted. Regardless, there have been many different approaches posted here, and im sure its more than enough for the OP to do what he wants.
|
Posted by BostonGuru, 08-02-2008, 04:50 PM |
I ran 100,000 cases of each formula then plugged them into excel. Both methods provide unique distributions. You can check them out below. They are kinda interesting.
http://www.irvinecollins.com/weighted_distributions.jpg
Note: I also found that your formula took about half the time for 100,000 iterations (.08s vs. .15s)
|
Posted by bigfan, 08-02-2008, 05:12 PM |
Good work. Thanks for that.
As for rand() vs. mt_rand(): I use the latter just because the manual says it's faster, even though any time I've tested them they've come out about the same.
|
Posted by Goldfiles, 08-03-2008, 03:54 PM |
Excellent, thanks for the help. This works great.
|
Add to Favourites Print this Article
Also Read