首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么兰德( $val )不警告当$val>2 **随机比特?

为什么兰德( $val )不警告当$val>2 **随机比特?
EN

Stack Overflow用户
提问于 2014-03-31 21:31:27
回答 3查看 214关注 0票数 4

我使用Strawberry Perl v5.16.2来构造一些假数据,使用对int rand 1_000_000的重复调用。经过相当多的混乱之后,我发现由于我的perl的randbits=15,上面的表达式只返回2**1532768可能的值。

代码语言:javascript
复制
>perl -V:randbits
randbits='15';

我的问题是:

  • 当有人试图使用rand $val where $val > 2 ** randbits时,为什么$val > 2 ** randbits不返回警告
  • 为什么perldoc rand根本不提这个问题?有一个关于如何"rand() is not cryptographically secure"的增编。我认为,这也值得一份增编,其中也提出了建议的替代解决办法。

设置

我试图创建一些假数据来测试一种算法,用于对平均20个重复的大量数据进行排序。这对1,000和10,000个条目都有效,但当我跳到1,000,000时,我发现我丢失了很多独特的值。

这似乎是一种统计上的不可能。在2000万拉环中不选择小于100万的特定整数的概率p(999_999/1_000_000) ** 20_000_0002.06e-9。所以不选择任何整数的概率是.2%

我很快就破解了另一个脚本,以确认我的假数据生成器中没有漏洞:

代码语言:javascript
复制
use strict;
use warnings;

use List::Util qw(sum max min);

our $max_count = 1_000;

my %count;

while (1) {
    my $val = int rand 1_000_000;
    last if ++$count{$val} > $max_count;
}

my $sum = sum values %count;
my $max = max values %count;
my $min = min values %count;
my $count = scalar keys %count;

print "$sum interations.  $count integers of expected 1mil with min $min, max $max\n";

产出:

代码语言:javascript
复制
28,958,579 interations.  32768 integers of expected 1mil with min 772, max 1001

显然,32,768是一个巨大的危险标志,它是2的强大力量,因此,为"perl rand does maximum 32768 integers"做一个快速的Googlefor"perl rand does maximum 32768 integers"返回了以下有用的资源:

前者是讨论这个问题的所有不同方面的一个很好的资源,并提供了用use Math::Random::MT qw(rand);use Math::Random::MT::Auto qw(rand);代替use Math::Random::MT qw(rand);的方法。

SO提供了an answer,其中包括一个不需要新模块安装的解决方案,只需为更多位调用rand两次。

代码语言:javascript
复制
use Config;
use constant RANDBITS => $Config{randbits};
use constant RAND_MAX => 2**RANDBITS;

sub double_rand {
    my $max = shift || 1;
    my $iv  =
          int rand(RAND_MAX) << RANDBITS
        | int rand(RAND_MAX);
    return $max * ($iv / 2**(2*RANDBITS));
}

幸运的是,这两个都解决了我最初的问题。不过,我很好奇.

  • rand的替代品有更好的下降吗?
  • 为什么perldoc rand中没有提到这个问题的两个句子增编?
  • 为什么warnings不警告大于2**randbits的值?如果有人想忽略这些警告,可能会有一个no warnings 'rand'调用,或者只是调用没有值的rand:val * rand
  • 我是否错误地安装了草莓Perl,最终得到了如此低的随机位数?有办法提高这个价值吗?这是用户的责任吗?

谢谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-06-13 19:37:43

是时候升级perl了。

perl v5.20 - perldelta开始

  • rand现在使用一致的随机数生成器。 以前,perl将使用特定于平台的随机数生成器,在libc ()、随机()或drand48()之间变化。 这意味着perl的随机数的质量将因平台而异,从Windows上的15位rand()到POSIX平台上的48位,比如Linux和drand48()。 Perl现在在所有平台上使用自己的内部drand48()实现。这并不能使perl的rand加密安全。perl #115928

我仍然希望,当rand的值大于2 ** randbits时,旧版本的perl会发出警告,但这是我所希望得到的最好的结果。

如果其他程序员无法升级的话,他们仍然需要警惕其他程序员,并继续推荐其他的选择,比如use Math::Random::MT qw(rand);

票数 0
EN

Stack Overflow用户

发布于 2014-03-31 22:06:19

您看过CPAN了吗,似乎有一些合适的资源。数学::BigInt::对于非常大的数字来说,随机似乎是一个很好的选择。

票数 0
EN

Stack Overflow用户

发布于 2014-04-02 02:58:14

对于非加密目的,请使用数学::随机::Mersenne Twister PRNG具有很好的特性。

您可以使用函数接口替换rand内置的内容:

面向功能的接口:

代码语言:javascript
复制
use Math::Random::MT qw(srand rand irand);
# now use srand() and rand() as you usually do in Perl
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22772578

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档