1

Will this following function always generate a unique string? What will be the length range of generated string from the following function? Can it be improved to generate more uniqueness?

base_convert(mt_rand(10, 99) . intval(microtime(true) * 100), 8, 36);

Thanks

sunjie
  • 2,023
  • 7
  • 28
  • 28
  • @KingCrunch i want a specific length, ie. maximum 6characters. – sunjie Jun 28 '11 at 06:29
  • Short answer? No. `microtime` will overflow with the epoch. – Cameron Skinner Jun 28 '11 at 06:30
  • Longer answer? You want a maximum of 6 characters? Then **no**. You'll have a maximum of 36^6 unique strings. Incidentally, why are you converting from base 8? And why to base 36? – Cameron Skinner Jun 28 '11 at 06:31
  • @sunjie: `substr(uniqid(), 0, 6);`? Maybe you should explain a little bit more, what you want to do with this string. – KingCrunch Jun 28 '11 at 06:32
  • check the accepted answer of http://stackoverflow.com/questions/5387755/how-to-generate-unique-order-id-just-to-show-touser-with-actual-order-id . This may help you. – Gaurav Jun 28 '11 at 06:33
  • @Cameron Skinner sorry, that should be from base 10. Any idea to make it better to get maximum 6 characters? – sunjie Jun 28 '11 at 06:35
  • 2
    A more "standard" way would be to simply hash the current time (and/or some other piece of request-specific data) and take 6 characters from the base-64-encoded hash. But 6 characters is very short. Is there a specific requirement that limits you to 6? What is the purpose of the unique string, and how unique do you need it to be (i.e. over what time frame and data volume, and how will you cope with a collision)? – Cameron Skinner Jun 28 '11 at 06:38
  • @Rafe: Ah, I see (excuse the pun). Thanks. – Cameron Skinner Jun 28 '11 at 06:59

3 Answers3

4

Keep in mind that it is generally a bad idea to write your own random/unique functions. Like KingCrunch mentioned PHP had a built-in function uniqid that does precisely what you want.

To answer your question:

The function will not always generate a unique string, it is impossible to do so. However good functions make it extremely unlikely (magnitudes of times smaller than winning the lottery) and thus unique enough in practice.

length:

  • mt_rand(10,99) : generates a number in the range [10,99] (2 digits)
  • intval(microtime(true)*100) will get the current unix timestamp plus 2 digits of the milliseconds. The timestamp is (at the moment) 10 digits long (and will remain so for about a century) so the total number of digits is 12 (decimal) digits

It then treats the number as a base_8 number this will fail often, as base_8 does not know the number 8 or 9. I do not know the exact PHP behaviour in this case but it is invalid nonetheless. If you act like the number is treated as base 10, you have the following scenario question: how much digits (base 36) are needed to represent numbers between 10^13 (if mt_rand generates 10) and 10^14 (if mt_rand generates 99).

The smallest number where base_36 needs 9 digits for is 2,821,109,907,457 which is lower than the underbound of your number. The largest number it can represent with 9 digits is however 101,559,956,668,416 (~10^14). Thus it will generate a 9-digit base_36 number.

[edit] I saw you specifically needed a 6-character unique string. Keep in mind that 6-characters is relatively short so uniqueness is hard to guarantee. Your best bet would still be

substr(uniqid(), 0, 6);

It will be better than any function you manage to come up on your own with.[/edit]

dtech
  • 13,741
  • 11
  • 48
  • 73
  • thanks for detailed reply. It was supposed to be from base 10, not 8. i want to generate a string with maximum 6 alphanumeric characters string with maximum uniqueness. can u suggest any solution? – sunjie Jun 28 '11 at 06:45
  • 2
    This is a very bad suggestion to use uniqid(). Basically uniqid() converts microtime() to a smaller string (simple base convertion). So, for example, first 5 chars from it will not change during an hour, so substr(uniqid(), 0, 6) will generate the same string during a long time (it surely would not be unique). Secondly, using even full uniqid() string will make you vulnerable to some attacks as it's values are very predictable: http://en.wikipedia.org/wiki/Random_number_generator_attack. But if you are not concerned about security - you can use substr(uniqid(),-6). – XzKto Jun 28 '11 at 07:18
1

Simple use uniqid() good inbuilt function. This also generate unique id from timestamp. So No. will always be unique.

Gaurav Porwal
  • 503
  • 3
  • 6
0

The answer to your question depends on your requirement. I use this function for a generic not-so-secure requirement. Only returns Alphabets and Numbers, clearing out "similar looking" characters: -

function fGetRandomString($vLength = 4) {
    $sRandomString = "";    $sChr = "";
    for ($i = 0 ; $i < $vLength ; $i++) {
        $vState = rand(1, 3);
            switch ($vState)    {
            case 1: $sChr = chr(rand(65, 90));  break;  // CAPS (A-Z)
            case 2: $sChr = chr(rand(97, 122)); break;  // small (a-z)
            case 3: $sChr = chr(rand(48, 57));  break;  // Numbers (0-9)
        }
        if (!in_array($sChr, array('O', 'o', '0', '1', 'l')))   $sRandomString .= $sChr;
        else    $i--;
    }
    return $sRandomString;
}

Good Luck!

M. Faraz
  • 412
  • 1
  • 6
  • 13