I've lost count of how many times I needed a conversion from a binary string ("1101...") to a signed integer. Each time I try to think of an elegant solution and end up with brute-force math (flip bits, add 1 to compute 2s complement, then use bin2dec). The binary->unsigned conversion is (from the Cookbook):
sub bin2dec { return unpack("N", pack("B32", substr("0" x 32 . shift, -32))); }
So, is there any way to apply pack/unpack magic to convert a binary string (of any length) to a signed, 2s complement integer ?
UPDATE:
Here is one solution
# Given a lsb-first bitstring, returns # a 2s complement signed integer # sub bin2signed { my $bitstr = $_[0]; my $is_negative = 0; if (substr($bitstr, -1, 1) eq "1") { $bitstr =~ tr/10/01/; $is_negative = 1; } my $result = 0; for (my $i = 0; $i < length($bitstr); ++$i) { $result += substr($bitstr, $i, 1) * (2 ** $i); } if ($is_negative) { $result += 1; $result *= -1; } return $result; }
In reply to signed bin2dec by spurperl
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |