Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Certain number of RAND numbers, but not repeated?

Status
Not open for further replies.

youradds

Programmer
Jun 27, 2001
817
GB
I'm trying to work out how to generate x number of random numbers, without repeating any of the numbers. The max number will vary, as its going to be a total weight of banners in theDB.

Cheers for any help you can offer :)

Andy
 
I don't think there's a built in functionality for this... I'm guessing you're going to have to do something like the following psuedo-code

function exist_yet(needle, haystack) {
if in_array(needle, haystack) {
return true;
}
return false;
}


for(i=0;i<x;i++) {
do {
temp=mt_rand(min,max);
} while (exist_yet(temp, list_of_nums) == true);
return temp;

list_of_nums[]=temp;
}

Where x is the number of randoms you want.

-Rob
 
woo hoo am I dumb, my exist_yet function does nothing... not to mention a couple typos...

so simplify that pseudo code to

for(i=0;i<x;i++) {
do {
temp=mt_rand(min,max);
} while (!in_array(temp, list_of_nums));

list_of_nums[]=temp;
}

and realize it has the danger of running into an infinite loop if the range between min,max is less than x.

-Rob
 
Hi...thanks for the reply...but I can't seem to get it to work. I'm getting this error;

Warning: Wrong datatype for second argument in call to in_array in c:\program files\nusphere\apache\nsdocs\test\popunder\popunder.php on line 59

Warning: Wrong datatype for second argument in call to in_array in c:\program files\nusphere\apache\nsdocs\test\popunder\popunder.php on line 59


etc...

Any ideas?

Cheers

Andy
 
depends on how you implemented it, that wasn't actually php code...

not to mention I had a typo (again, sorry!)

here's the whole function and a sample call to it.

Code:
<?

function random_nums($x=10, $min=0, $max=10000) {

  $list_of_nums = array();
  for($i=0;$i<$x;$i++) {
    $temp=mt_rand($min,$max);
    while(in_array($temp, $list_of_nums)) {
      $temp=mt_rand($min,$max);
    }
    $list_of_nums[]=$temp;
  }
  
  return $list_of_nums;
}

$list_of_nums = random_nums();

foreach($list_of_nums as $num) {
  echo &quot;$num<BR>&quot;;
}

?>


 
and if you're just curious, the most likely error you were having was calling in_array with the second type an undefined variable, while it needs to be an array.

-Rob
 
Sorry to litter the thread, but if you're putting this in some real code, don't forget that you want something akin to

if (($max-$min) < $x) {
echo &quot;Impossible, this will be an infinite loop&quot;;
return some kind of error;
} else {
execute the above
}

 
Hopefully this makes sense.

A good way of generating a list of numbers, with the possibility of numbers either coming up multiple times or not, with weighting possible, is to fill an array with a list of all numbers you want to allow to come up, repeated appropriately for weighting. So, say you have three different numbers, one that you want to come up 5 times in 10, one 3 times in 10 and the last 2 times in 10. You would populate an array like:
array=(1 1 1 1 1 2 2 2 3 3)

Now, if you just wanted to pick randomly, based on the weighting, you would just randomly generate numbers 1 through 10 and use the number at that position. You would have a chance of picking &quot;1&quot; every time, but more the numbers would come out statistically averaging your desired weighting.

If you wanted to force the occurrences, you would do this loop 10 times:
Pick a number from 1 to length(array)
Take the element at the selected position
Remove that element from the array

So, say the first time you selected the number 4. That would give you item '1' and the new array would look like:
array=(1 1 1 1 2 2 2 3 3) (notice it's now 9 in length)

So, now you pick a random number from 1 to 9. Say you pick 5. You get item '2' and the array is now:
array=(1 1 1 1 2 2 3 3)

If you keep doing this until the array is empty you will have picked out your 5 1s, 3 2s and 2 3s in a random order.

This method also works if you want non-repeating numbers. You would just initially populate the array with n different numbers.

This is a much faster method than checking to see if you've picked a number before for every number you pick, particularly after you've picked most of the available numbers.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top