in reply to Randomizing Unique ID?

Any algorithm using "random" numbers risks repition. What you want is a unique number. Something like $$ . time (Thats the process ID concatenated with the epoch.) If you want it to use letters and such, change the base after generating the number. Here is an algorithm for that:
# For a positive $number my @nums = (0..9,'a'..'z','A'..'Z'); my $base = @nums; my $rep = ""; # this will be the end value. while( $number > 0 ) { $rep = $nums[$number % $base] . $rep; $number = int( $number / $base ); }
(Thanks Tye for looking over my shoulder and helping construct that simple algorithm)

Replies are listed 'Best First'.
RE: RE: Randomizing Unique ID?
by tye (Sage) on Aug 09, 2000 at 21:54 UTC

    Note that this is barely adequate since a "typical" double has 53 bits of mantissa (not counting the sign bit) which can handle just under 16 decimal digits while time() currently returns 9 digits but will soon return 10, while $$ is typically no more than 5 digits (total will soon be 15 digits).

    Doing the conversion to base-62 in two steps would give you lots of room (and different results).

            - tye (but my friends call me "Tye")
      Well, If you want more room in the double, then do the base conversion before doing the concatenation, thusly:
      # Generate a truly unique ID sub GenerateBase { my $base = shift; $base = 62 if $base > 62; my @nums = (0..9,'a'..'z','A'..'Z')[0..$base-1]; return sub { my $number = shift; my $rep = ""; # this will be the end value. while( $number > 0 ) { $rep = $nums[$number % $base] . $rep; $number = int( $number / $base ); } return $rep; } } my $ToBase62 = GenerateBase( 62 ); my $ID = $ToBase62->( $$ ) . $ToBase62->( time );
RE: RE: Randomizing Unique ID?
by turnstep (Parson) on Aug 10, 2000 at 00:00 UTC

    However, the risk of repetition is more than outweighed by the new risk of predictability, especially using time and a process ID (yes, some smarter OS's have non-sequential PIDs). I do not think the issue of repetition is much of a risk. In the example the original poster used, the chance of a repetition is about 1 in 10^31. I'll take those odds any day. :)

      The rand() solutions are nearly as predictable, since rand() is deterministic and the latest Perl's seed function is deterministic based on $$, time(), and PL_stack_sp (except on some platforms). That last value, at the time it is checked, is probably often constant across invocations of the same script.

      The odds are much worse than 1/10^31 as the entire sequence from rand() is deterministic based on the seed. Perhaps you meant 1/2^32, which presumes a completely random seed, which you don't have.

      If you want to avoid predictability, then use Math::TrulyRandom (or encrypt using a secret key, if you think you can keep it secret) as others suggested.

      At least Perl has a much better seed generator these days.

      Also, even 1/2^31 would be the odds of a single duplicate. If you have lots of IDs with overlapping lifetimes, then the odds rise surprising fast. If you rarely have more than a few IDs active at once, then 1/2^31 might well be acceptable. But if it is possible, for example, to have 6600 simultaneous IDs, you get about a 1% chance of a collisions per batch of IDs; which probably isn't acceptable.

              - tye (but my friends call me "Tye")
        Good point regarding the deterministic sequence by using rand. In that case, bump the number of characters up to 16, or even 32 (which I've seen in a few URLs). Should be much better odds then (it's too early to actually calculate them now :)
      You can have the best of both worlds. Use a combination of randomness and uniqueness to make the output unique. Something like, (and I am building on the code in RE: RE: RE: Randomizing Unique ID? ):
      my $ID = $ToBase62->( $$ ) . $ToBase62->( rand( $$ ) ) . $ToBase62->( +time );
      Not forgeting to call srand() at some point.
      And of course, you can use whatever rand() you want.

      Update: Don't bother seeding. Tye explains the internal seed here. Also, see the Base Conversion Utility.