What is the best way to create a 20 digit random number and to ensure that it is not a duplicate from the prior such random numbers generated?
Of course I have an idea of how to do this?
But I am sure this is a class of a problem that others have dealt with before, so there much be much existing wisdom, experience and code in this regard. So I would very much like to know what suggestions you all have for handling the above described task.
The numbers are generated over time.
Of course one answer would be to store the numbers in a MySQL DB and make sure that a duplicate number is not generated by looking at this table 1st.
But I am wondering if there are other perfect (100% fail safe) ways of doing this. One idea of I have to do this without looking at a DB 1st is to have the numbers generated based on day and time + a random number. But that random number would have to be unique for that day for sure.
Well the only way to -guarantee- uniqueness is to use a defined function (which precludes randomness), or to store the existing values somehow for exclusion later.
Purely numeric? Or are alpha characters allowed? If the latter then use MD5() with a seed and the current timestamp? (This gives a 32 character string, working on the basis that you want a “random” unique identifier as your primary concern, and 20 characters is a secondary matter).
if that were the case you’d just use session_id (which is a 27-40 character string)
simple fact is that the odds of a 20-digit random number (0-9) not being unique are <numberofpreviousvisitors>/100 quintillion (100,000,000,000,000,000,000). Alphanumeric? (0-9a-zA-Z) is <numberofpreviousvisitors>/7.04e35 (704,424,525,546,998,022,968,330,264,616,370,176).
Answers to some of the questions:
1- yes the numbers need to be random so the user X cannot compute what the code for user X+1 is
2- The code should be numeric since numeric values are much faster to look up in a SB than are string values
3- I guess the best answer is to make each code to be made off:
year+month+day+random 10 digit value
so this way we should not need to look up the code 1st in the DB to make sure it is unique since the chance of it being unique will be so remote
str_replace(’ ‘,’',microtime()).str_pad(rand(1,1000000000),10,‘0’) should really be sufficient… the chances of a collision require 2 people to hit your code at the exact same microsecond, AND a 1 in a billion chance
(if you’re not fussy about the lenght, kill the str_pad and you’ll have a variable length number between 10 and 20)
the largest number that you can store is 18,446,744,073,709,551,615 which is the maximum value of an UNSIGNED BIGINT – so you will need to be very careful that your randomly generated 20-digit number does not exceed this value
my advice would be to use a UUID instead, such as ‘6ccd780c-baba-1026-9564-0040f4311e29’
That’s not quite right. 1e19 / 1e20 = 10% but you actually get a 50% chance of a duplicate at roughly the square root, or about 1e10. And for alpha 3.5e35 / 7e35 = 50%, but it’s more like 8e17.
At any rate I’d recommend using one of the already available methods for generating UUIDs, or if you really have to, go with StarLions method. The time is unique every second (or microsecond), so no matter what you append to it it will still be unique.
How do you figure?
There are 62^20 different 20-character AlphaNum strings. Every time you assign one, 1 of those possibilities being a duplicate is added. Therefore the odds are <numberofpreviousvisitors>/(62^20). Simple probability (assuming of course that the RNG is actually random, which is a whole other debate)
google “birthday problem”. Once you have 23 people in a room there is a 50% chance that two will share a birthday. But 23/365 = 6%. Strange, but mathematically true.
function generateCode ($length = 4)
{
// start with a blank password
$vCode = "";
// define possible characters
$possible = "0123456789bcdfghjkmnpqrstvwxyz";
// set up a counter
$i = 0;
// add random characters to $password until $length is reached
while ($i < $length)
{
// pick a random character from the possible ones
$char = substr($possible, mt_rand(0, strlen($possible)-1), 1);
// we don't want this character if it's already in the password
if (!strstr($vCode, $char))
{
$vCode .= $char;
$i++;
}
} // done!
return $vCode;
}
And this guarantees uniqueness… how? (Save you some time, it doesn’t. In fact, this thing generates a rather weak password, given that it’s a non-repeating choose 20 from 31.)