2012-04-26 22 views
6

Usando Perl, sin usar ningún módulo extra que no venga con ActivePerl, ¿cómo puedo crear una cadena de 8 caracteres de 0 a F? ejemplo 0F1672DA? El relleno debe ser controlable y es preferible exactamente 8 caracteres.En Perl, ¿cómo puedo generar cadenas aleatorias que constan de ocho dígitos hexadecimales?

Más ejemplos de los tipos de cadenas que me gustaría generan:

28DA9782 
55C7128A 
+5

Golf: 'perl -e'print [0..9, A..F ] -> [rand 16] para 1..8'' – daxim

+1

¿Por qué downvoting? Necesito aprender programación. ¿Para qué sirve stackoverflow si no es este tipo de preguntas? – unixman83

+4

No he votado tu publicación. Sin embargo, en general, descartar cualquier módulo de CPAN no se considera favorablemente. Además, se espera que haga un esfuerzo para llegar a una solución propia, y pida ayuda con eso en lugar de esperar que otros le den soluciones enlatadas. –

Respuesta

15

En principio, debería ser capaz de hacer

#!/usr/bin/env perl 

use strict; use warnings; 

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

Sin embargo, es posible descubrir que — al menos en algunos sistemas con algunos perl s (si no todos) — la range of rand is restricted to 32,768 values.

También puede estudiar el código fuente de String::Random para aprender a generar cadenas aleatorias que satisfagan otras condiciones.

Sin embargo, mi precaución contra el uso del built in rand en el sistema de Windows sigue en pie. Consulte Math::Random::MT para obtener un RNG de alta calidad.

#!/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:

Esto significaba que la calidad de números aleatorios de Perl podría variar de una plataforma a otra, a partir de los 15 bits de rand() en Windows de 48 bits en las plataformas POSIX como Linux con drand48().

Perl ahora usa su propia implementación interna de drand48() en todas las plataformas. Esto no hace que el rayo de Perl sea criptográficamente seguro. [Perl # 115928]

+0

Seguramente hay un complemento que viene con ActivePerl que supera el límite de 'rand'? – unixman83

+0

+1 para la advertencia 'rand' – unixman83

+1

¿Una solución sería usar' rand' para 1 dígito a la vez? ¿Tu segundo ejemplo hace esto? – unixman83

4

Uso sprintf para convertir los números en hexadecimal.

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

+1 por simplicidad – unixman83

7

Ejemplo general, permitiendo a cualquier rango de caracteres:

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

algunas personas mencionaron la ventanas del límite del rand con el MAX-Valor de rand (0x7FFF) o rand (32768) decimal, lo haría superar este cambio con el binario-operador < < '

# 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)) 
    ); 

pero considero esto en como académico, porque es un código realmente incómodo que es difícil de entender.
No utilizaría esto en el código de la vida real, solo si la velocidad es máxima.
Pero quizás es la solución más rápida y está demostrando un esquema para superar la limitación de la función rand() en Windows ...

+0

Esto no funcionará de acuerdo con @Sinan. ¡El rango de 'rand' es solo de 32.768! – unixman83

+3

Mi afirmación fue algo más débil: * En al menos algunos sistemas de Windows, el rango de 'rand' podría estar limitado a 32.768 valores. –

+0

Sí, ya leí el blog. –

Cuestiones relacionadas