如何在Perl中生成非重复的随机4字节十六进制值?

时间:2009-12-14 07:02:23

标签: perl

我想生成随机十六进制值,这些值不应该重复  它应该是4个字节(即:0x00000000到0xffffffff)和显示输出  应该包含前导零。

例如:如果我得到值1,则不应表示为0x1而是0x00000001。

我想要至少100个随机值。请告诉我:我怎么能在Perl中做到这一点?

5 个答案:

答案 0 :(得分:9)

获得0 ...(2 <&lt; 32)-1:

范围内的随机数
my $rand = int(rand(0x100000000));

以十六进制打印前导零:

printf "%08x", $rand;

请在Perl手册页中注明:

  

注意:如果您的rand函数始终返回数字                  太大或太小,那么你的Perl版本可能编译错误的RANDBITS数量

如果这是一个问题,请改为:

printf "%04x%04x", int(rand(0x10000)), int(rand(0x10000));

另请注意,这对防止重复没有任何作用,但老实说,100个数字序列中重复32位数的可能性非常小。

如果您不重复这一点绝对必要,请执行以下操作:

my (%a);                       # create a hash table for remembering values
foreach (0 .. 99) {
    my $r;
    do {
        $r = int(rand(0x100000000));
    } until (!exists($a{$r})); # loop until the value is not found
    printf "%08x\n", $r;       # print the value
    $a{$r}++;                  # remember that we saw it!
}

对于它的价值,如果可能值的范围小于(或甚至接近)所需值的数量,则不应使用此算法。那是因为随机数生成器循环只会反复拉出已经看过的数字。

然而,在这种情况下,可能的范围是如此之高(2 ^ 32)并且值的数量如此之低,它将完美地工作。事实上,这个范围很高,这是唯一实用的算法。

答案 1 :(得分:4)

perl -e 'printf "%08X\n", int rand 0xFFFFFFFF for 1 .. 100'

答案 2 :(得分:4)

Alnitak explained it,但这是一个更简单的实现。我不确定每个人是如何开始接触do {} while的,因为这是一个非常奇怪的选择:

my $max = 0xFFFF_FFFF;

my( %Seen, @numbers );

foreach ( 1 .. 100 )
    {
    my $rand = int rand( $max + 1 );
    redo if $Seen{$rand}++;
    push @numbers, $rand;
    }

print join "\n", map { sprintf "0x%08x", $_ } @numbers;

另外,正如Alnitak指出的那样,如果你产生了很多数字,那么redo可能会循环很多次。

这些只是伪随机数,但你并不是真的要求真正的随机数。这将涉及可能的重复。 :)

答案 3 :(得分:3)

use LWP::Simple "get";
use List::MoreUtils "uniq";
print for uniq map { s/\t//, "0x$_" } split /^/, LWP::Simple::get('http://www.random.org/integers/?num=220&min=0&max=65535&col=2&base=16&format=plain&rnd=date.2009-12-14');

调整网址(请参阅http://www.random.org/integers/?mode=advanced上的表单)并不总是返回相同的列表。没有返回至少100个结果的可能性微乎其微。

请注意,这个答案有意“差”作为对这个糟糕问题的评论。这不是一个单独的问题,它是一堆全部包含在一起,所有我已经打赌已经存在的答案(如何在x范围内生成一个随机数,如何将数字格式化为带有0x的十六进制字符串和0填充,如何仅将唯一值添加到列表中,等等。这就像问“如何在Perl中编写Web服务器?”在没有猜测提问者真正想要答案的部分的情况下,你要么必须为回复写一本书,要么说:

perl -MIO::All -e 'io(":80")->fork->accept->(sub { $_[0] < io(-x $1 ? "./$1 |" : $1) if /^GET \/(.*) / })'

答案 4 :(得分:2)

获取随机整数:

int(rand(0x10000000))

将其格式化为8个十六进制数字:

printf "%08x", int(rand(0x10000000))