PHP rand与Perl rand的区别

3

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?


13
抱歉,我必须这样做:http://xkcd.com/221/ - deceze
2
依赖于从 rand 返回的一致数字集合指向代码中更深层次的问题。我希望这只是一个好奇心,而不是某种移植问题。如果是后者,请从 Perl 和 PHP 进行一次“随机”数字转储,进行必要的映射,然后消除对非随机随机数的依赖。 - unpythonic
@Mark:这取决于代码的功能。例如,许多游戏提供随机地图生成,并告诉您任何特定地图使用的种子,因此您可以使用该种子在未来重播相同的地图(或将其发送给朋友等),而无需提供“保存地图”功能。这是依赖可重复序列的(伪)随机数的完全有效用例。如果不知道OP的代码是做什么的,我们就不能判断是否适合这种依赖性。 - Dave Sherohman
@Dave - 很好的观点。希望它适合你的用例,而不是我所想象的。 - unpythonic
@Dave:是的,没错。我已经相应修改了问题。 - bhups
@Dave Sherohman,对于游戏中这样的用途,您不想使用大多数语言内置的rand()函数。它们非常依赖于系统,并且除非另有说明,否则可能会发生变化。 - Ven'Tatsu
3个回答

8
是的,你不能依赖它们的算法相同。对于Perl来说,使用哪个rand取决于你的Perl是为哪个平台构建的。
也许您可以更幸运地使用特定的算法;例如,Mersenne Twister似乎适用于PHPPerl
更新:尝试使用它会产生不同的结果,所以至少这个算法行不通。
更新2:根据您展示的Perl数字,您的Perl正在使用drand48库;我不知道PHP是否有这个库,谷歌也没有帮助。

2

[小夹子]看起来你想要对一个数字进行哈希,也许你想使用哈希函数?[/小夹子]

哈希函数旨在接受输入并产生一个外观随机但一致可重复的值。作为额外的好处,它们通常具有跨语言实现。

使用srand()rand()获取基本上是哈希值的内容是一个相当糟糕的想法。不同的语言使用不同的算法,有些只使用系统库。更改(或升级)操作系统、标准C库或语言可能导致结果大不相同。

使用SHA1获得介于1和2000之间的数字有点过头了,但您至少可以确信您可以将代码移植到几乎任何语言,并仍然得到相同的结果。

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.

0

仅凭这段代码片段是不可能说它是否相同的。

首先,您需要知道即使像rand()函数这样的随机生成器也不是真正的随机。它使用从前一个数字计算出的数学公式来计算新值。使用srand()函数可以设置起始值。

每次使用相同的参数调用srand()意味着程序总是以相同的顺序返回相同的数字。

如果您真的想要随机数,在Perl中应该删除srand()的初始化。因为当您第一次调用rand()函数时,Perl会自动将srand()设置为更好(随机)的值。

如果您的程序确实需要随机数,那么在PHP中也应该可以。但是即使在PHP中,我也会查看srand()是否被自动设置并设置为更随机的值。

如果您的程序不使用随机数,而是真正希望获得始终相同的数字流,则代码片段可能不相同。即使您使用相同的srand()初始化,PHP也可能使用另一个公式来计算下一个“随机”数字。

所以,如果你的代码真的需要随机数,那么你需要查看周围的代码,如果是这样,你可以使用这段代码。但即使如此,你也应该寻找更好的srand()初始化方法。


3
如果你真的想要随机数,那么你根本不会使用rand()。 - brian d foy
当然,rand()对于密码学来说不够随机,但对于许多情况来说已经足够了。我认为我已经回答了这个问题,它是否足够好。我不认为负评是正确的,即使你提到rand()不够随机。 - David Raab
1
@Sid 就提供更多的随机性而言,一粒种子并不比另一粒更好。无论生成器的质量如何,这些都是“伪随机”数字。因此,如果你真正想要“随机”数字,你应该使用其他东西,这就是 Brian 要表达的意思。 - Sinan Ünür
Perl会自动选择一个随机种子,而不是静态的。因此,不设置srand()可以得到“更好”的随机数。这并不意味着它们不是伪随机生成的。问题的重点在于PHP代码和Perl代码是否相同,而不是伪随机数生成器的好坏。 - David Raab
我说,这取决于应用程序对数字的处理方式。如果应用程序将这些数字用作随机数,则代码相等。如果应用程序将数字用作应始终返回相同数字的流,则代码不相等。real是他的应用程序如何处理数字的方式。而不是rand()是否返回真正的随机数。关于rand()是否返回真正的随机数的整个讨论只是浪费时间,也不是问题,也不是我所说的。我已经在第二句话中说过了,rand()不会返回真正的随机数。 - David Raab

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接