LayoutPH
LayoutPH

Reputation: 409

Generating unique random numbers from 10000000 to 99999999

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

Answers (3)

ToBe
ToBe

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

DerVO
DerVO

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

Ole Haugset
Ole Haugset

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

Related Questions