generate number
Moderators: egami, macek, gesf
-
- New php-forum User
- Posts: 193
- Joined: Sat Mar 29, 2003 11:57 pm
- Location: Auckland, New Zealand
- Contact:
Oh yes it can.
This is a function I wrote to generate a random string.
Then to check that it doesn't already exist in the database.
This is a function I wrote to generate a random string.
Code: Select all
function RandomString($length=8)
{
//Generate alphabet array
$alphabet = "";
for ($i = 0; $i < 26; $i++) {
@$alphabet .= chr(97+$i).",";
}
$alphabet = explode(",", $alphabet);
$RandomString = "";
//Check that length is between 1 and 40
if ($length > 40 || $length < 1) {
$length = 8;
}
//Generate Random string
for ($i = 1; $i <= $length; $i++) {
$rand = rand(0, 25);
$RandomString .= $alphabet[$rand];
}
return $RandomString;
}
Then to check that it doesn't already exist in the database.
Code: Select all
//Connect to database
//Select database
$sql = mysql_query("SELECT * FROM table WHERE field = '".RandomString()."'");
if (mysql_num_rows($sql) > 0) {
echo "RandomString is already taken";
}
else {
echo "Not taken";
}
- swirlee
- Moderator
- Posts: 2257
- Joined: Sat Jul 05, 2003 1:18 pm
- Location: A bunk in the back
- Contact:
Joel wrote:Code: Select all
function RandomString($length=8)
{
//Generate alphabet array
$alphabet = "";
for ($i = 0; $i < 26; $i++) {
@$alphabet .= chr(97+$i).",";
}
$alphabet = explode(",", $alphabet);
$RandomString = "";
//Check that length is between 1 and 40
if ($length > 40 || $length < 1) {
$length = 8;
}
//Generate Random string
for ($i = 1; $i <= $length; $i++) {
$rand = rand(0, 25);
$RandomString .= $alphabet[$rand];
}
return $RandomString;
}
It seems to me you're doing quite a lot of extra work here, or at the very least, using two or three times as much memory as you need to. Also, the poster asked for a random string of letters and numbers, which I usually take as being [A-Z][a-z][0-9], though I'm sure this is up for interpretation. I came up with two ways to do this. The first works, but isn't very streamlined. The second is very streamlined, skipping all of the conditionals nonsense and using only one loop and the very useful (but rarely used, for some reason) curly braces string-access-by-character syntax.
Method 1:
Code: Select all
<?
function rand_string($length = 16) {
$rand_string = '';
$choice = 0;
for($i = 0, $i < $length; $i++) {
// pick lowercase, uppercase, or number
$choice = rand(0,2);
switch($choice) {
case 0: // lowercase
$num = rand(0, 25);
$rand_string .= chr(97 + $num);
break;
case 1: // uppercase
$num = rand(0, 25);
$rand_string .= chr(65 + $num);
break;
case 2: // number
$rand_string .= rand(0, 9);
break;
}
}
return $rand_string;
}
?>
Here's the second method, far simpler and likely faster:
Method 2:
Code: Select all
<?
function rand_string($length = 16) {
// list all valid characters (faster than generating them on-the-fly)
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' .
'abcdefghijklmnopqrstuvwxyz' .
'0123456789';
$chars_len = strlen($chars);
$rand_string = '';
for($i = 0, $i < $length, $i++) {
$rand_string .= $chars{rand(0, $chars_len - 1)};
}
return $rand_string;
}
?>
This can very easily be pared down to just 8 lines, but why bother?
Both of the functions are used by calling rand_string() and optionally specifying a string length (which could be determined randomly, of course).
-
- New php-forum User
- Posts: 193
- Joined: Sat Mar 29, 2003 11:57 pm
- Location: Auckland, New Zealand
- Contact:
I have taken a liking to the second function there, the only painful part is the typing of all the letters, but hey, you've only got to do it once right.
You could even spice it up by the random length, and have the max length and min length adjustable. Or in other words, Swirlee, I love you.
You could even spice it up by the random length, and have the max length and min length adjustable. Or in other words, Swirlee, I love you.
- swirlee
- Moderator
- Posts: 2257
- Joined: Sat Jul 05, 2003 1:18 pm
- Location: A bunk in the back
- Contact:
Joel wrote:Or in other words, Swirlee, I love you.
LOL. 8O
Actually, I found that just typing out all of the letters and numbers took less time than coding the for() loop. But I did discover one basic flaw: If you're anal about statistics and want a given character to have an equal probability of being a lowercase, uppercase, or numeral, my script won't work, simply because there are 16 more uppercase and lowercase letters than there are numerals (in other words, you have about a 42% chance of getting a lowercase, 42% chance of getting an uppercase, but only about a 16% chance of getting a numeral). The way to fix this, essentially, is to combine the two functions into a hybrid:
Code: Select all
<?
function rand_string($length = 16) {
// each set of characters is in a different array element
$chars = array(
'ABCDEFGHIJKLMNOPQRSTUVWXYZ', // uppercase
'abcdefghijklmnopqrstuvwxyz', // lowercase
'0123456789' // numerals
);
$rand_string = '';
for($i = 0, $i < $length, $i++) {
// choose a set of characters at random
$which_list = rand(0, count($chars));
// choose a character (index) from that set
$which_char = rand(0, strlen($chars[$which_list]));
// append the character to $rand_string
$rand_string .= $chars[$which_list]{$which_char};
}
return $rand_string;
}
?>
Note that I'm not sure if the syntax on the append line -- $array[$string_index]{$char_index} -- will actually work, as I can't test it on this machine. You may have to copy the array element to a new string before using the access-by-character syntax.
Last edited by swirlee on Sat Jul 26, 2003 10:53 pm, edited 1 time in total.
the functions both of you have written are great and i know the odds of getting a replica in the database are slim and none but if it does return back to me as already existing in the database, how do i make it keep regenerating until none is found so i may then insert that string.
thanks for all your help
thanks for all your help
-
- New php-forum User
- Posts: 193
- Joined: Sat Mar 29, 2003 11:57 pm
- Location: Auckland, New Zealand
- Contact:
Code: Select all
do {
$randomstring = RandomString();
$sql = mysql_query("SELECT * FROM table WHERE field = '".$randomstring."'");
} while (mysql_num_rows($sql) > 0;
Although, I didn't really think that through, but it should work.
i was just wondering what yall thought about this function. i tried using the other functions and i want it to return a 16 character string everytime but sometimes it comes back as 8 or 9 or 4 or 10, or 15, and so on
function randomstring()
{
$char = "abchefghjkmnpqrstuvwxyz0123456789";
srand((double)microtime()*1000000);
$i = 0;
while ($i <= 16) {
$num = rand() % 33;
$tmp = substr($char, $num, 1);
$string = $string . $tmp;
$i++;
}
function randomstring()
{
$char = "abchefghjkmnpqrstuvwxyz0123456789";
srand((double)microtime()*1000000);
$i = 0;
while ($i <= 16) {
$num = rand() % 33;
$tmp = substr($char, $num, 1);
$string = $string . $tmp;
$i++;
}
- swirlee
- Moderator
- Posts: 2257
- Joined: Sat Jul 05, 2003 1:18 pm
- Location: A bunk in the back
- Contact:
Was it your intention to have only 23 letters in your alphabet, two of which are "h"? Just curious.
Anyway, your code will work, but unless your RAND_MAX happens to be a multiple of strlen($char), you won't get an even distribution. This may or may not matter to you. I don't know what the default for RAND_MAX happens to be. It's far easier just to specify a min and max for the rand() function and will yield the same result. And it should be noted that if you're running a PHP version 4.2 or later, it's no longer necessary to seed the random number generator.
And as far as general coding (which I'm always compelled to pick on people about, sorry, it's my vice), using a for() instead of a while() loop will save you two lines of code, and most programmers prefer to use the concatenation operator ($a .= $b) instead of the method you employ ($a = $a . b).
Anyway, your code will work, but unless your RAND_MAX happens to be a multiple of strlen($char), you won't get an even distribution. This may or may not matter to you. I don't know what the default for RAND_MAX happens to be. It's far easier just to specify a min and max for the rand() function and will yield the same result. And it should be noted that if you're running a PHP version 4.2 or later, it's no longer necessary to seed the random number generator.
And as far as general coding (which I'm always compelled to pick on people about, sorry, it's my vice), using a for() instead of a while() loop will save you two lines of code, and most programmers prefer to use the concatenation operator ($a .= $b) instead of the method you employ ($a = $a . b).
thankx. if i were to use your code how could i make it return 16 characters everytime..
if i'm not mistaken wouldn't the loop keep repeating until $length is reached which just happens to be 16 which would give me a string 16 characters long.
if i'm not mistaken wouldn't the loop keep repeating until $length is reached which just happens to be 16 which would give me a string 16 characters long.
- swirlee
- Moderator
- Posts: 2257
- Joined: Sat Jul 05, 2003 1:18 pm
- Location: A bunk in the back
- Contact:
Heh. I just got the chance to actually test my code for the first time, and I find that you've discovered a tiny bug -- occasionally (at random), it would skip a character because I forgot to subtract 1 from my count() (count() returns the number of elements, not the maximum index, of an array). Also, I was using commas instead of semicolons in my for() loop. Oops. Anyway, here's the fixed code:
By the way, if you want only lowercases and numerals, just delete the uppercase array element. Likewise for the other elements.
Some charming strings generated by the function:
y16w5UGIlxlAK3ac, FvHSTJE7HZIlrAO, OU106U072aTklf2t, u87M3sDDC15WH0KZ, and sSDGfRijnyO8g37.
Code: Select all
<?
function rand_string($length = 16) {
// each set of characters is in a different array element
$chars = array(
'ABCDEFGHIJKLMNOPQRSTUVWXYZ', // uppercase
'abcdefghijklmnopqrstuvwxyz', // lowercase
'0123456789' // numerals
);
$rand_string = '';
for($i = 0; $i < $length; $i++) {
// choose a set of characters at random
$which_list = rand(0, count($chars) - 1);
// choose a character (index) from that set
$which_char = rand(0, strlen($chars[$which_list]));
// append the character to $rand_string
$rand_string .= $chars[$which_list]{$which_char};
}
return $rand_string;
}
?>
By the way, if you want only lowercases and numerals, just delete the uppercase array element. Likewise for the other elements.
Some charming strings generated by the function:
y16w5UGIlxlAK3ac, FvHSTJE7HZIlrAO, OU106U072aTklf2t, u87M3sDDC15WH0KZ, and sSDGfRijnyO8g37.
Last edited by swirlee on Mon Jul 28, 2003 6:14 am, edited 1 time in total.

-
- New php-forum User
- Posts: 193
- Joined: Sat Mar 29, 2003 11:57 pm
- Location: Auckland, New Zealand
- Contact:
I made the one adjustment, which Swirlee mentioned and printed the random string 2000 times and checking if any were not 16 characters. This is the function I used. (Swirlees)
Code: Select all
function rand_string($length = 16) {
// each set of characters is in a different array element
$chars = array(
'ABCDEFGHIJKLMNOPQRSTUVWXYZ', // uppercase
'abcdefghijklmnopqrstuvwxyz', // lowercase
'0123456789' // numerals
);
$rand_string = '';
for($i = 0; $i < $length; $i++) {
// choose a set of characters at random
$which_list = rand(0, count($chars) - 1);
// choose a character (index) from that set
$which_char = rand(0, strlen($chars[$which_list]) - 1);
// append the character to $rand_string
$rand_string .= $chars[$which_list]{($which_char)};
}
return $rand_string;
}
after testing it again it still came up with a random length. but i changed it a little bit and again all it was were a few parenthesis.
i placed the parenthesis on the $which_car statement around the ($chars[$which_list]) --- now it's perfect
Code: Select all
function rand_string($length = 16) {
// each set of characters is in a different array element
$chars = array(
'ABCDEFGHIJKLMNOPQRSTUVWXYZ', // uppercase
'abcdefghijklmnopqrstuvwxyz', // lowercase
'0123456789' // numerals
);
$rand_string = '';
for($i = 0; $i < $length; $i++) {
// choose a set of characters at random
$which_list = rand(0, count($chars) - 1);
// choose a character (index) from that set
$which_char = rand(0, strlen(($chars[$which_list])) - 1);
// append the character to $rand_string
$rand_string .= $chars[$which_list]{($which_char)};
}
return $rand_string;
}
i placed the parenthesis on the $which_car statement around the ($chars[$which_list]) --- now it's perfect

- swirlee
- Moderator
- Posts: 2257
- Joined: Sat Jul 05, 2003 1:18 pm
- Location: A bunk in the back
- Contact:
How this one thread has gotten so much attention boggles the mind.
Anyway, I just stumbled across the uniqid() function which generates a unique ID based on the time. It's not random -- it appears to just convert the time to base 16 -- but it works if you don't need something random. If you want something that at least looks a little more random, do md5(uniqid(''));
Anyway, I just stumbled across the uniqid() function which generates a unique ID based on the time. It's not random -- it appears to just convert the time to base 16 -- but it works if you don't need something random. If you want something that at least looks a little more random, do md5(uniqid(''));