Generating random results by weight in PHP?
Based on @Allain's answer/link, I worked up this quick function in PHP. You will have to modify it if you want to use non-integer weighting.
/** * getRandomWeightedElement() * Utility function for getting random values with weighting. * Pass in an associative array, such as array('A'=>5, 'B'=>45, 'C'=>50) * An array like this means that "A" has a 5% chance of being selected, "B" 45%, and "C" 50%. * The return value is the array key, A, B, or C in this case. Note that the values assigned * do not have to be percentages. The values are simply relative to each other. If one value * weight was 2, and the other weight of 1, the value with the weight of 2 has about a 66% * chance of being selected. Also note that weights should be integers. * * @param array $weightedValues */ function getRandomWeightedElement(array $weightedValues) { $rand = mt_rand(1, (int) array_sum($weightedValues)); foreach ($weightedValues as $key => $value) { $rand -= $value; if ($rand <= 0) { return $key; } } }
For an efficient random number skewed consistently towards one end of the scale:
- Choose a continuous random number between 0..1
- Raise to a power γ, to bias it. 1 is unweighted, lower gives more of the higher numbers and vice versa
- Scale to desired range and round to integer
eg. in PHP (untested):
function weightedrand($min, $max, $gamma) { $offset= $max-$min+1; return floor($min+pow(lcg_value(), $gamma)*$offset);}echo(weightedrand(1, 10, 1.5));
There's a pretty good tutorial for you.
Basically:
- Sum the weights of all the numbers.
- Pick a random number less than that
- subtract the weights in order until the result is negative and return that number if it is.