Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 为什么兰德($val)在$val>;时不发出警告;2**兰比特?_Perl - Fatal编程技术网

Perl 为什么兰德($val)在$val>;时不发出警告;2**兰比特?

Perl 为什么兰德($val)在$val>;时不发出警告;2**兰比特?,perl,Perl,我使用v5.16.2通过重复调用来构造一些伪数据。在经历了相当多的困惑之后,我发现因为我的perl的randbits=15,上面的表达式将只返回2**15或32768可能的值 >perl -V:randbits randbits='15'; 我的问题是: 当有人试图使用rand$valwhere$val>2**randbits时,为什么不返回警告 为什么不提这个问题呢?有一个附录说明了“rand()如何在加密方面不安全”。我认为,这也值得一份附录,并提出替代解决方案 设置 我试图创建

我使用
v5.16.2
通过重复调用来构造一些伪数据。在经历了相当多的困惑之后,我发现因为我的perl的
randbits=15
,上面的表达式将只返回
2**15
32768
可能的值

>perl -V:randbits
randbits='15';
我的问题是:

  • 当有人试图使用
    rand$val
    where
    $val>2**randbits
    时,为什么不返回警告
  • 为什么不提这个问题呢?有一个附录说明了
    “rand()如何在加密方面不安全”
    。我认为,这也值得一份附录,并提出替代解决方案
设置

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

这在统计上似乎是不可能的。在2000万次拉取中不选择小于100万的特定整数的概率
p
(999\u 999/1\u 000\u 000)**20\u 000\u 000
2.06e-9
。因此,任何整数不被选择的概率是
.2%

我迅速拼凑出另一个脚本,以确认我的假数据生成器中没有缺陷:

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";
产出:

28,958,579 interations.  32768 integers of expected 1mil with min 772, max 1001
显然,
32768
2
强大的一面巨大的红旗,因此快速搜索返回了以下有用的资源:

前者是讨论该问题所有不同方面的一个很好的资源,并提供了使用和替换
rand

SO post提供了一个不需要安装新模块的解决方案,只需调用
rand
两次即可获得更多比特

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));
}
使用Config;
使用常量RANDBITS=>$Config{RANDBITS};
使用常数RAND_MAX=>2**RANDBITS;
亚双色兰{
我的$max=shift | | 1;
我的四美元=

int rand(rand_MAX)你看过了吗?似乎有一些合适的资源。Math::BigInt::Random对于非常大的数字来说似乎是一个很好的资源。

对于非加密目的,使用。具有很好的属性

您可以使用功能界面作为内置的
rand
替代品:

面向功能的接口: 是时候升级perl了

  • rand
    现在使用一致的随机数生成器

    以前,perl将使用特定于平台的随机数生成器,在libc rand()、random()或drand48()之间变化

    这意味着perl随机数的质量会因平台而异,从Windows上的15位rand()到POSIX平台上的48位,如Linux with drand48()

    Perl现在在所有平台上都使用自己的内部drand48()实现。这并不能使Perl的
    rand
    加密安全

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


仍然需要注意Windows上的其他程序员,并继续推荐替代方案,例如如果他们无法升级。

它是否应该为rand(1000)发出警告?因为这也是有偏见的。re“我是否安装了草莓Perl,以如此低的randbits结束?”,不,这是C库提供的。re“是否有更好的替代品替代兰德?”,如文件中所述,CPAN提供了加密质量的随机数生成器。@ikegami我认为,
rand
文件已经在附录中提到了
rand(1000)
不“加密安全”的偏向性“虚假声明是文档的第一句话“返回一个大于或等于0且小于EXPR值的随机分数”我不期望完美的随机性,但这确实意味着在0和EXPR之间可能存在32768个以上的值。但是文档中没有提到这一点。无论如何,“谢谢”为了快速反馈。明天某个时候我会打电话给PM。@Miller,这是另一个问题。
rand(1000)
有偏见,因为1000不是2的幂。
use Math::Random::MT qw(srand rand irand);
# now use srand() and rand() as you usually do in Perl