2.14 Generating Unique Random Numbers


2.14 Generating Unique Random Numbers

You want to ensure that the same random number does not appear twice.

Technique

Keep a database of numbers already stored and query that database:

 <?php require_once 'DB.php'; class Unique_Random {     var $dbh;     // Constructor, sets initial variables     // $connstring is the database connection string     function Unique_Random ($connstring)     {         $this->dbh = new DB($connstring);         if (DB::isError ($dbh))             die (sprintf ('Error [%d]: %s',                           $dbh->getCode(), $dbh->getMessage()));         mt_srand ((double)microtime() * 1000000);     }     // Private function to check and see whether $number is     // in the database     // $number is the number to check for.     function _check ($number)     {         $stmt = "SELECT num FROM num_table WHERE num='$number'";         $sth = $this->dbh->query ($stmt);         if (DB::isError ($sth))             die (sprintf ('Error [%d]: %s',                           $sth->getCode(), $sth->getMessage()));         return ($sth->numRows);     }     // Private function to add a number to the database     // $number is the number to add     function _add ($number)     {         $stmt = "INSERT INTO num_table (num) VALUES ('$num')";         $sth  = $this->dbh->query ($stmt);         if (DB::isError ($sth))             die (sprintf ('Error [%d]: %s',                           $sth->getCode(), $sth->getMessage()));     }     // Private function to generate the random number     function _generateNumber ()     {         return md5 (uniqid (mt_rand(), 1)) + getmypid();     }     // {{{ random_number()     /**      * Generates a random number that is not present within      * the num field of the num_table table of your database.      *      * @return double the generated random number      */     function random_number ()     {         $number = $this->_generate_number();         while (!$this->_check ($number))             $number = $this->_generate_number();         $this->_add ($number);         return ($number);     }     // }}} } $connstring = "odbc://sterling:secret@localhost/numbers"; $generator = new Unique_Random($connstring); $number = $generator->random_number(); print "$number is $number, it has never been generated before"; ?> 

Comments

In the Unique_Random class, we use DB (a PHP 4 module, distributed through PEAR), which enables us to access the database without making database-specific function calls. For more information about DB , consult the PEAR documentation or Chapter 16, "Creating a Database-Independent API with PHP."

The concept behind the Unique_Random class is quite simple: We generate a random number and then check whether that number is stored in the database. If the number is not stored in the database, it is unique, so we add it to the database and return it. Otherwise we generate another random number and perform the same check.

Although we use a relational database to store the numbers to see whether the number was generated, we could just have easily done this with file access and the serialize() function. (For brevity, I'll omit the cleaner OO syntax and show a less advanced example.)

 <?php mt_srand ((double)microtime() * 1000000); $data = implode ("", file ('random_numbers.txt')); $random_numbers = $data ? unserialize ($data) : array (); $random = mt_rand(); while (in_array ($random_numbers, $random))     $random = mt_rand(); array_push ($random_numbers, $random); $data = serialize ($random_numbers); $fp = @fopen ("random_numbers.txt", 'w'); if (!$fp) {     die ("Cannot open random_numbers.txt"); } @fwrite ($fp, $data); @fclose ($fp); print "$random has not been generated before"; ?> 


PHP Developer's Cookbook
PHP Developers Cookbook (2nd Edition)
ISBN: 0672323257
EAN: 2147483647
Year: 2000
Pages: 351

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net