Bitfelder aus beliebig grossen Zahlen extrahieren

29/07/2008 - 14:15 von hofer | Report spam
Hi,


Kontext:
Ich will mit grossen Integers arbeiten (meistens unsigned)
die Groesse ist oft groesser als 64 bit, also fallen ordinaere perl
scalars schon mal weg.

Ich dachte als repraesentation fuer meine Zahlen an als Math::BigInt.

wirkt ja nicht so schwer


Zahlen erzeugen:
my $a = Math::BigInt->new("0x7777666655544443333222211110000");
my $b = Math::BigInt->new("0x1111111111111111111111111111111");

jetzt kann ich ein bischen rechnen.
$a->badd($b); # $a = $a + $b

Und nun wuerd ich gerne ein paar bits aus dieser grossen Zahl
extrahieren:

Beispiel Bits 16 bis 12 sollte 0b00001 == 0x1 == 1 ergeben
Bits 17 bis 12 sollte 0b100001 == 0x21 == 33 ergeben

Bis jetzt mach ich das manuel und nicht sehr elegant:


sub extbits { #
my ($val,$msb,$lsb) = @_; # $val must be Math::BigInt;
my $asbinstr = $val->as_bin(); # nun als binaer string
my $withoutprefix = substr($asbinstr,2); # fuehrendes '0b'
entfernen
my $substr = substr($withoutprefix,-$msb-1,$msb-$lsb+1); # den
substring extrahieren
$substr = 0 if $substr eq ""; # sollte mindestens einen character
enthalten
my $result = Math::BigInt->new("0b".$substr); # zurueck in
Math::BigInt verwandeln
return $result;
} #


Hat da irgendwer eine bessere Idee?


Vielen Dank im Voraus und by

H
 

Lesen sie die antworten

#1 hofer
29/07/2008 - 14:32 | Warnen spam
Ja genau, es gibt natuerlich noch eine andere Variante,

# extract bits via shifts followed by a bit wise and
sub extbits { #/*{{{*/
my ($val,$msb,$lsb) = @_; # $val must be Math::BigInt;
my $mask = Math::BigInt->new(1); # create a 1
$mask->blsft($msb-$lsb+1); # 2 ^ (number of bits to extract)
$mask->bsub(1); # now we have a mask
my $tmp = $val->copy->brsft($lsb); # shift input value to the
right
return $tmp->band($mask);
} #/*}}}*/


On Jul 29, 2:15 pm, hofer wrote:
Hi,

Kontext:
Ich will mit grossen Integers arbeiten (meistens unsigned)
die Groesse ist oft groesser als 64 bit, also fallen ordinaere perl
scalars schon mal weg.

Ich dachte als repraesentation fuer meine Zahlen an als Math::BigInt.

wirkt ja nicht so schwer

Zahlen erzeugen:
my $a = Math::BigInt->new("0x7777666655544443333222211110000");
my $b = Math::BigInt->new("0x1111111111111111111111111111111");

jetzt kann ich ein bischen rechnen.
$a->badd($b); # $a = $a + $b

Und nun wuerd ich gerne ein paar bits aus dieser grossen Zahl
extrahieren:

Beispiel Bits 16 bis 12 sollte 0b00001 == 0x1 == 1 ergeben
Bits 17 bis 12 sollte 0b100001 == 0x21 == 33 ergeben

Bis jetzt mach ich das manuel und nicht sehr elegant:

sub extbits { #
my ($val,$msb,$lsb) = @_; # $val must be Math::BigInt;
my $asbinstr = $val->as_bin(); # nun als binaer string
my $withoutprefix = substr($asbinstr,2); # fuehrendes '0b'
entfernen
my $substr = substr($withoutprefix,-$msb-1,$msb-$lsb+1); # den
substring extrahieren
$substr = 0 if $substr eq ""; # sollte mindestens einen character
enthalten
my $result = Math::BigInt->new("0b".$substr); # zurueck in
Math::BigInt verwandeln
return $result;

} #

Hat da irgendwer eine bessere Idee?

Vielen Dank im Voraus und by

H

Ähnliche fragen