我想生成随机十六进制值,这些值不应该重复 它应该是4个字节(即:0x00000000到0xffffffff)和显示输出 应该包含前导零。
例如:如果我得到值1,则不应表示为0x1而是0x00000001。
我想要至少100个随机值。请告诉我:我怎么能在Perl中做到这一点?
答案 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))