【问题标题】:Php rand vs Perl randphp rand vs Perl rand
【发布时间】:2011-07-08 06:39:10
【问题描述】:

我正在尝试将一段代码从 perl 移植到 php。 perl 代码 sn-p 是 akamai 的视频点播链接生成脚本的一部分。该脚本根据视频文件的位置/ URL 生成种子(对于单个 URL,它始终是不变的)。然后它用于生成流的序列号(基本上是使用种子的 1 到 2000 之间的随机数)。这是perl代码。

$seed=6718;
srand($seed);
print(int(rand(1999)) + 1); // return 442 every time
转换后的 PHP 代码是:
$seed=6718;
srand($seed);
echo(rand(0, 1999) + 1); //returns 155 every time
php rand 的行为是否与 perl one 不同?

【问题讨论】:

  • 对不起,我必须:xkcd.com/221
  • 依赖从rand返回的一组一致的数字指向代码中更深层次的问题。我希望这只是一个好奇心,而不是一些移植问题。如果是后者,从 perl 和 PHP 中一次性转储“随机”数字,做任何你需要做的映射,然后移除对非随机随机数的依赖。
  • @Mark:取决于代码在做什么。例如,许多游戏提供随机地图生成,并且还会告诉您任何特定地图使用的种子,因此您可以使用该种子在未来重播同一张地图(或将其发送给朋友等),而无需提供用于“保存地图”功能。对于依赖于(伪)随机数的可重复序列,这是一个完全有效的用例。在不知道 OP 的代码做了什么的情况下,我们无法判断这样的依赖是否合适。
  • @Dave - 好点。好吧,希望它适合您的用例,而不是我的想象。
  • @Dave:是的,这是正确的。我已经相应地修改了问题。

标签: php perl random


【解决方案1】:

是的。你不能依赖他们的算法是一样的。对于 perl,使用哪个 rand 取决于您的 perl 是为什么平台构建的。

使用特定算法可能会更幸运;例如,Mersenne Twister 看起来可用于PHPPerl。 更新:尝试它会产生不同的结果,因此至少不会成功。

更新 2:根据您显示的 perl 编号,您的 perl 正在使用 drand48 库;我不知道这是否适用于 PHP,谷歌也没有帮助。

【讨论】:

    【解决方案2】:

    [clippy]看起来你正在尝试散列一个数字,也许你想使用散列函数?[/clippy]

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

    使用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.
    

    【讨论】:

      【解决方案3】:

      仅仅看到这个sn-p的代码就无法说它是否相同。

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

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

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

      如果你的程序真的需要随机数,那么 PHP 也应该没问题。但即使在 PHP 中,我也会查看 srand() 是否自动设置并设置为更随机的值。

      如果您的程序不使用随机数,而是真的想要一个始终相同的数字流,那么代码片段可能并不相同。即使您使用 srand() 进行相同的初始化,PHP 也可能使用另一个公式来计算下一个“随机”数。

      因此,如果您的代码确实需要随机数,则需要查看周围的代码,如果是,则可以使用此代码。但即便如此,您也应该为 srand() 寻找更好的初始化方法。

      【讨论】:

      • 如果你真的想要随机数,你根本不会使用 rand()。
      • 当然,rand() 对于密码学来说不够随机,但在很多情况下它就足够了。我想我已经回答了这个问题是否足够好。而且我认为反对票是不正确的。即使你提到 rand() 也不够随机。
      • @Sid 在某种意义上提供更多随机性方面,一个种子并不比另一个更好。无论生成器的质量如何,这些都是伪随机数。所以,如果你真的想要 random 数字,你会使用其他东西,这是 brian 试图提出的观点。
      • Perl 自动选择随机种子,而不是静态种子。所以不设置 srand() 可以“更好”的随机数。这并不意味着它们不是伪生成的。问题的重点是 PHP 代码和 Perl 代码是否相同。不是伪随机数生成器有多好。
      • 我说过,这取决于应用程序如何处理这些数字。如果应用程序将该数字用作随机数,则代码是相等的。如果应用程序将数字用作应始终返回相同数字的流,则代码不相等。 real 是他的应用程序如何线程化数字。如果rand() 返回真正的随机数,则不会。如果rand() 返回真正的随机数,整个讨论只是很短的时间,不是问题,也不是我所说的。我在第二句话中已经说过rand() 不会返回真正的随机数。
      猜你喜欢
      • 2015-04-07
      • 1970-01-01
      • 1970-01-01
      • 2017-10-28
      • 1970-01-01
      • 1970-01-01
      • 2019-01-30
      • 1970-01-01
      相关资源
      最近更新 更多