bhups
bhups

Reputation: 14885

Php rand vs Perl rand

I am trying to port a piece of code from perl to php. The perl code snippet is part of akamai's video on demand link generation script. The script generates seed based on the location / URL of the video file (which will always be constant for a single URL). And then it is used in generating serial ID for stream (which is basically a random number between 1 and 2000 using the seed). Here is the perl code.

$seed=6718;
srand($seed);
print(int(rand(1999)) + 1); // return 442 every time
And the converted PHP code is:
$seed=6718;
srand($seed);
echo(rand(0, 1999) + 1); //returns 155 every time
Does php rand behaves differently than perl one?

Upvotes: 3

Views: 629

Answers (3)

Ven'Tatsu
Ven'Tatsu

Reputation: 3635

[clippy]It looks like your trying to hash a number, maybe you want to use a hash function?[/clippy]

Hash functions are designed to take an input and produce a consistently repeatable value, that is in appearance random. As a bonus they often have cross language implementations.

Using srand() with rand() to get what is basically a hash value is a fairly bad idea. Different languages use different algorithms, some just use system libraries. Changing (or upgrading) the OS, standard C library, or language can result in wildly different results.

Using SHA1 to get a number between 1 and 2000 is a bit overkill, but you can at least be sure that you could port the code to nearly any language and still get the same result.

use Digest::SHA1;

# get a integer hash value from $in between $min (inclusive) and $max (exclusive)
sub get_int_hash {
    my ($in, $min, $max) = @_;

    # calculate the SHA1 of $in, note $in is converted to a string.
    my $sha  = Digest::SHA1->new;
    $sha->add( "$in" );
    my $digest = $sha->hexdigest;
    # use the last 7 characters of the digest (28 bits) for an effective range of 0 - 268,435,455.
    my $value = hex substr $digest, -7;
    # scale and shift the value to the desired range.
    my $out = int( $value / 0x10000000 * ( $max - $min ) ) + $min;

    return $out;
}
print get_int_hash(6718, 1, 2000); #this should print 812 for any SHA1 implementation.

Upvotes: 2

David Raab
David Raab

Reputation: 4488

Just seeing this snippet of code it is impossible to say if it is the same.

At first you need to knew that even a random generator like the rand() function is not really random. It calculates a new value with a mathematical formula from the previous number. With the srand() function you can set the start value.

Calling srand() with the same argument each time means that the program always returns the same numbers in the same order.

If you really want random numbers, in Perl you should remove the initialization of srand(). Because Perl automatically sets srand() to a better (random) value when you first call the rand() function.

If your program really wants random numbers, then it should also be okay for PHP. But even in PHP i would look if srand() is automatically set and set to a more random value.

If your program don't work with random numbers and instead really want a stream of numbers that is always the same, then the snipet of code are probably not identical. Even if you do the same initialization with srand() it could be that PHP uses another formula to calculate the next "random" number.

So you need to look at your surrounding code if you code really wants random numbers, if yes you can use this code. But even then you should look for a better initialization for srand().

Upvotes: 0

ysth
ysth

Reputation: 98398

Yes. You can't depend on their algorithms being the same. For perl, which rand is used depends on what platform your perl was built for.

You may have more luck using a particular algorithm; for instance, Mersenne Twister looks to be available for both PHP and Perl. Update: trying it produces different results, so that one at least won't do the trick.

Update 2: From the perl numbers you show, your perl is using the drand48 library; I don't know whether that's available for PHP at all, and google isn't helping.

Upvotes: 8

Related Questions