I'm trying to convert a bitstring to a signed 32 bit integer value. The bitstring is in big-endian. I can get this to work for unsigned values, I use:

``````sub bin2dec {
return unpack("N", pack("B32", substr("0" x 32 . shift, -32)));
}``````

But I can't get it to work signed values. "N" is unsigned by default and there is no signed equivalent. The closest alternative is "i", which I have tried, but gives a bogus number because it defaults to 64 bits for me. I also tried "l" but that seems to be giving something completely wrong; I think it might be expecting a different memory ordering... any ideas?

Please show us an example of a negative bitstring. I think that since you say "big-endian" you have generated your bitstring according to the 2's Complement method but I'm not sure about that.

There are two methods for storing negative binary numbers, they are Sign and Magnitude and 2's Complement.

yeah, I'm using two's compliment
0xFFFFFFFF (stored in binary bitstring)
should be -1, but it is showing up as 4294967295

yeah, I'm using two's compliment
0xFFFFFFFF (stored in binary bitstring)
should be -1, but it is showing up as 4294967295

You said you already tried the 'l' template and it gave you something wrong. On my computer it seems to work OK. Did you test it in something like the following way?

0xFFFFFFFF (stored in binary bitstring) would be a string of 32 1's, right?

``````#!/usr/bin/perl
use strict;
use warnings;

my \$bitstring = '1' x 32; #String of 32 1's

my \$pl = pack 'l', \$bitstring; #Create a packed long integer

my (\$num) = unpack 'l', \$pl;

print \$num; #Prints -1``````

After posting the above I tried substituting 'l' for 'N' in your original script and it also printed -1 for me, so I guess the problem is you are running it on a different platform. I'm using Ubuntu 10.04.3 LTS and my computer is 32-bit.

``````#!/usr/bin/perl
use strict;
use warnings;

print bin2dec('1' x 32); #Prints -1

sub bin2dec {
return unpack("l", pack("B32", substr("0" x 32 . shift, -32)));
}``````