On Sat, 11 Oct 2003 23:04:33 GMT, "Alexander Ross" <al******@bleen.net> wrote:

is there any way to get a weighted random number other than something like

this:

array = (1,2,2,3,3,3,4,4,4,5,5,6)

and then get a random val from teh array?

Yes, but that's probably the simplest. You can produce that array from an

array of weights if you wanted.

<pre>

<?php

function weighted_rand($weights) {

foreach ($weights as $value => $weight)

for ($i=0; $i<$weight; $i++)

$values[] = $value;

return $values[mt_rand(0, count($values)-1)];

}

$num_runs = 40000;

$weights = array(1=>1, 2=>2, 3=>3);

for ($i=0; $i < $num_runs; $i++) {

$rand = weighted_rand($weights);

if (isset($results[$rand]))

$results[$rand]++;

else

$results[$rand] = 1;

}

ksort($results);

$total_weight = 0;

foreach ($weights as $weight)

$total_weight += $weight;

foreach ($results as $value => $freq) {

printf("%d : expected %8d (%3.2f%%), actual %8d (%3.2f%%)\n",

$value,

$num_runs * ($weights[$value] / $total_weight),

($weights[$value] / $total_weight) * 100.0,

$freq, $freq/$num_runs * 100.0);

}

?>

</pre>

Outputs:

1 : expected 6666 ( 16.67%), actual 6624 ( 16.56%)

2 : expected 13333 ( 33.33%), actual 13383 ( 33.46%)

3 : expected 20000 ( 50.00%), actual 19993 ( 49.98%)

Or you could skip creating the array with repeated values and work directly

off the weight array:

function weighted_rand($weights) {

$total_weight = 0;

foreach ($weights as $weight)

$total_weight += $weight;

$rand = mt_rand(1, $total_weight);

$total_weight = 0;

foreach ($weights as $value => $weight) {

$total_weight += $weight;

if ($rand <= $total_weight)

return $value;

}

}

Output to make sure it's still weighting correctly:

1 : expected 6666 ( 16.67%), actual 6554 ( 16.38%)

2 : expected 13333 ( 33.33%), actual 13352 ( 33.38%)

3 : expected 20000 ( 50.00%), actual 20094 ( 50.23%)

--

Andy Hassall (an**@andyh.co.uk) icq(5747695) (

http://www.andyh.co.uk)

Space: disk usage analysis tool (

http://www.andyhsoftware.co.uk/space)