【问题标题】:In Perl, how can I generate random strings consisting of eight hex digits?在 Perl 中,如何生成由八个十六进制数字组成的随机字符串?
【发布时间】:2012-05-07 09:02:54
【问题描述】:

使用 Perl,不使用 ActivePerl 不附带的任何额外模块,如何创建从 0 到 F 的 8 个字符的字符串。例如0F1672DA?填充应该是可控的,最好是 8 个字符。

我想生成的字符串类型的更多示例:

28DA9782
55C7128A

【问题讨论】:

  • 高尔夫:perl -e'print[0..9,A..F]->[rand 16]for 1..8'
  • 为什么要投反对票?我确实需要学习编程。如果不是这类问题,stackoverflow 是什么?
  • 我没有否决您的帖子。然而,一般来说,排除任何 CPAN 模块是不受欢迎的。此外,您应该付出一些努力来提出自己的解决方案,并寻求帮助,而不是指望别人给您罐装的解决方案。
  • CPAN 对 ActiveState 来说是个痛点。 :) 我推荐 Strawberry Perl。
  • @Quentin - 我在 AS perl 上的 CPAN 没有太多问题。他们通过 ppm (ppm inst dmake, ppm inst mingw) 提供 C 编译器和 dmake。我更喜欢 cpanm 直接从 cpan (ppm inst App::cpanminus) 安装模块。

标签: string random activeperl perl


【解决方案1】:

原则上你应该可以做到

#!/usr/bin/env perl

use strict; use warnings;

for (1 .. 10) {
    printf "%08X\n", rand(0xffffffff);
}

但是,您可能会发现 — 至少在某些具有一些 perls(如果不是全部)的系统上 — range of rand is restricted to 32,768 values

你也可以学习String::Random的源码,学习如何生成满足其他条件的随机字符串。

但是,我对在 Windows 系统上使用内置 rand 的警告仍然有效。请参阅Math::Random::MT 以获得高质量的 RNG。

#!/usr/bin/env perl

use strict; use warnings;

my @set = ('0' ..'9', 'A' .. 'F');
my $str = join '' => map $set[rand @set], 1 .. 8;
print "$str\n";

PS:The issue with Perl's rand on Windows was fixed in 5.20

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

Perl 现在在所有平台上都使用它自己的内部 drand48() 实现。这不会使 perl 的 rand 加密安全。 [perl #115928]

【讨论】:

  • 肯定有一个ActivePerl自带的插件可以突破rand的限制?
  • 解决方案是否会一次使用rand 一位数字?你的第二个例子是这样做的吗?
  • 是的,第二种方法确实使用类似于@Oleg 的方法(我投票赞成)的自适应@set 一次生成一个数字的字符串。
【解决方案2】:

一般示例,允许任意范围的字符:

my @chars = ('0'..'9', 'A'..'F');
my $len = 8;
my $string;
while($len--){ $string .= $chars[rand @chars] };
print "$string\n";

【讨论】:

    【解决方案3】:
    sprintf("%08X", rand(0xFFFFFFFF))
    

    有些人提到了 rand 的窗口限制和 rand(0x7FFF) 或 rand(32768) 十进制的最大值,我会用二进制移位运算符 '

    # overcomes the windows-rand()-only-works-with-max-15bit-(32767)-limitation:
    #   needed 8*4==32bit random-number:
    #     first get the 15 high-significant bits shift them 17bits to the left,
    #     then the next 15bits shifted 2 bits to the left,
    #     then the last 2 bits with no shifting:
    printf( '%08X', (
        (rand(0x8000)<<17) + (rand(0x8000)<<2) + rand(0b100) )
          );
    

    但我认为这只是学术性的,因为它确实是难以理解的笨拙代码。
    我不会在实际代码中使用它,除非速度最重要。
    但也许它是最快的解决方案,它展示了一种模式来克服 windows 下 rand() 函数的限制......

    【讨论】:

    • 根据@Sinan,这不起作用。 rand 的范围仅为 32,768!
    • 我的说法有点弱:*至少在某些 Windows 系统上,rand 的范围可能限制为 32,768 个值。
    • 我认为 Sinan Ünür 应该提交错误报告,如果这是真的。 rand() 返回值仅包含 32768 个不同的数字。 perldoc -f 告诉我 rand 应该返回一个小数。根据文档和我自己的测试,我认为我的解决方案是正确的。
    • 为什么不能提交错误报告? :)
    • Lutz 和@briandfoy 问题在于rand implementation that comes with Windowsrand 函数返回一个范围为0 到RAND_MAX (32767) 的伪随机整数平台限制。即使将来某个时间 perl 的某些构建更改为其他 rand,原则仍然存在:如果您关心 rand 产生的内容,那么请使用已定义好的属性。
    【解决方案4】:

    使用sprintf 将数字转换为十六进制。

    $foo .= sprintf("%x", rand 16) for 1..8;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-06
      • 2012-05-10
      • 1970-01-01
      • 2015-03-29
      • 2021-06-28
      • 1970-01-01
      • 2018-03-12
      • 1970-01-01
      相关资源
      最近更新 更多