Reputation: 409
I need to create unique random pins using numbers only. I need to produce between 10,000,000 and 99,999,999. I need to create 100,000 pins
Here's the code I am currently using:
function UniqueRandomNumbersWithinRange($min, $max, $quantity) {
$numbers = range($min, $max);
shuffle($numbers);
return array_slice($numbers, 0, $quantity);
}
print_r( UniqueRandomNumbersWithinRange(10000000,99999999,100000));
This code still runs okay with my server using 50000 but not with 100000 items. Can you help me, is there code that can produce this many unique numbers without using too much memory in the server?
Upvotes: 3
Views: 1752
Reputation: 2681
Small idea; do a range($min, $quantity) and then multiply all generated numbers by $max / $quantity. This would drastically reduce your $numbers array and still have the correct range.
function UniqueRandomNumbersWithinRange($min, $max, $quantity) {
$numbers = range(0, $quantity);
shuffle($numbers);
array_walk($numbers, function(&$value, $key, $params) {
$value = floor($params[0] + $value * ($params[1]-$params[0]) / $params[2]);
}, array($min, $max, $quantity));
return $numbers;
}
print_r( UniqueRandomNumbersWithinRange(10000000,99999999,100000));
Upvotes: 0
Reputation: 3679
The range()
uses just to much memory; you generate an array of 90,000,000 int
values, each 8 bytes big on your 64 bit machine. This makes it an 686 MB array.
So we need to generate every number on its own and check, if it's already in your result array (to ensure, every number is unique)
function UniqueRandomNumbersWithinRange($min, $max, $quantity) {
if ($max - $min < $quantity * 10) return false;
$unique_numbers = array();
while (count($unique_numbers) < $quantity) {
$random_number = mt_rand($min, $max);
if (!in_array($random_number, $unique_numbers)) $unique_numbers[] = mt_rand($min, $max);
}
return $unique_numbers;
}
The first line inside the function checks, if there are enough numbers between $min
and $max
available, to generate $quantity
unique numbers; otherwise we get an infinite loop here. I added a factor of 10, so there is some space for randomness ;)
Upvotes: 0
Reputation: 3797
I believe this should do the trick for you:
<?php
function UniqueRandomNumbersWithinRange($min, $max, $quantity) {
$i = 0;
$numbers = array();
while( $i <= $quantity ){
$numbers[$i] = mt_rand($min, $max);
$i++;
}
print_r( $numbers );
}
UniqueRandomNumbersWithinRange(10000000,99999999,100000);
?>
As of the comment to my answer, there is a posibility of multiple keys containing the same pin. This code will eliminate duplicates, but takes a lot more computing time:
<?php
function UniqueRandomNumbersWithinRange($min, $max, $quantity) {
$i = 0;
$numbers = array();
while( $i <= $quantity ){
$number = mt_rand( $min, $max );
if( !in_array( $number, $numbers ) ){
$numbers[$i] = $number;
$i++;
}
}
print_r( $numbers );
}
UniqueRandomNumbersWithinRange(10000000,99999999,100000);
?>
Upvotes: 1