Usate pack() e unpack() o anche vec() e le operazioni a livello di bit.
Per esempio, questo imposta ad 1 i bit di $vet le cui posizioni sono contenute
in @posizioni:
$vet = '';
foreach(@posizioni) { vec($vet,$_,1) = 1 }
Ecco come, dato un vettore in $vet, potete ottenere quei bit nel vostro
array @interi:
sub vetbit_in_lista {
my $vet = shift;
my @interi;
# Trova la densita` dei byte nulli poi seleziona l'algoritmo migliore
if ($vet =~ tr/\0// / length $vet > 0.95) {
use integer;
my $i;
# Questo metodo e` piu` veloce avendo byte in maggioranza nulli
while($vet =~ /[^\0]/g ) {
$i = -9 + 8 * pos $vet;
push @interi, $i if vec($vet, ++$i, 1);
push @interi, $i if vec($vet, ++$i, 1);
push @interi, $i if vec($vet, ++$i, 1);
push @interi, $i if vec($vet, ++$i, 1);
push @interi, $i if vec($vet, ++$i, 1);
push @interi, $i if vec($vet, ++$i, 1);
push @interi, $i if vec($vet, ++$i, 1);
push @interi, $i if vec($vet, ++$i, 1);
}
} else {
# Questo metodo e` un algoritmo veloce e generale
use integer;
my $i_bit = unpack "b*", $vet;
push @interi, 0 if $i_bit =~ s/^(\d)// && $1;
push @interi, pos $i_bit while($i_bit =~ /1/g);
}
return \@interi;
}
Questo metodo va tanto più veloce quanto più sparso
è il vettore di bit. (Per gentile concessione di Tim Bunce e
Winfried Koenig.)
Potete rendere il ciclo while molto più breve con questo
suggerimento di Benjamin Goldberg:
while($vet =~ /[^\0]+/g ) {
push @interi, grep vec($vet, $_, 1), $-[0] * 8 .. $+[0] * 8;
}
Oppure usate il modulo CPAN, Bit::Vector:
$vettore = Bit::Vector->new($numero_di_bit);
$vettore->Index_List_Store(@interi);
@interi = $vettore->Index_List_Read();
Bit::Vector fornisce dei metodi efficienti per vettori di bit, insiemi
di piccoli interi e matematica per grandi interi.
Ecco una più estesa illustrazione dell'uso di vec():
# dimostrazione di vec
$vettore = "\xff\x0f\xef\xfe";
print "La stringa di Ilya \\xff\\x0f\\xef\\xfe rappresenta il numero ",
unpack("N", $vettore), "\n";
$settato = vec($vettore, 23, 1);
print "Il suo 23esimo bit vale ", $settato ? "1" : "0", ".\n";
pvet($vettore);
imposta_vet(1,1,1);
imposta_vet(3,1,1);
imposta_vet(23,1,1);
imposta_vet(3,1,3);
imposta_vet(3,2,3);
imposta_vet(3,4,3);
imposta_vet(3,4,7);
imposta_vet(3,8,3);
imposta_vet(3,8,7);
imposta_vet(0,32,17);
imposta_vet(1,32,17);
sub imposta_vet {
my ($posizione, $ampiezza, $valore) = @_;
my $vettore = '';
vec($vettore, $posizione, $ampiezza) = $valore;
print "posizione=$posizione ampiezza=$ampiezza valore=$valore\n";
pvet($vettore);
}
sub pvet {
my $vettore = shift;
my $i_bit = unpack("b*", $vettore);
my $i = 0;
my $BASE = 8;
print "lunghezza del vettore in byte: ", length($vettore), "\n";
@i_byte = unpack("A8" x length($vettore), $i_bit);
print "i bit sono: @i_byte\n\n";
}
|