Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting bitstring to 32-bit signed integer yields wrong result

I am trying to solve a challenge on this site. I have everything correct except I can't properly convert a bitstring to its 32-bit signed integer representation.

For example I have this bitstring:

block = '10101010001000101110101000101110'

My own way of converting this bitstring to 32-bit signed integer: I partially remember from school that first bit is the sign bit. If it is 1 we have negative number and vice versa.

when I do this, it gives me the number in base 10. It just converts it to base 10:

int(block, 2) #yields 2854414894

I have tried excluding the first bit and convert remaining 31 length bitstring, after that checked the first bit to decide whether this is negative number or not:

int(block[1:32], 2) #yields 706931246

But the correct answer is -1440552402. What operation should I do to this bitstring to get this integer? Is it relevant if the byte order of the system is little endian or big endian? My system is little endian.

like image 720
Bora Avatar asked Jan 16 '26 21:01

Bora


2 Answers

In python there's no size for integers, so you'll never get a negative value with a high order 1 bit.

To "emulate" 32-bit behaviour just do this, since your 2854414894 value is > 2**31-1 aka 0x7FFFFFFF:

print(int(block[1:32], 2)-2**31)

you'll get

-1440552402
like image 144
Jean-François Fabre Avatar answered Jan 19 '26 15:01

Jean-François Fabre


You're right that the upper bit determines sign, but it's not a simple flag. Instead, the whole character of negative numbers is inverted. This is a positive number 1 (in 8 bits):

00000001

This is a negative 1:

11111111

The upshot is that addition and subtraction "wrap around". So 4 - 1 would be:

0100 - 0001 = 0011

And so 0 - 1 is the same as 1_0000_0000 - 1. The "borrow" just goes off the top of the integer.

The general way to "negate" a number is "invert the bits, add 1". This works both ways, so you can go from positive to negative and back.

In your case, use the leading '1' to detect whether negation is needed, then convert to int, then maybe perform the negation steps. Note, however, that because python's int is not a fixed-width value, there's a separate internal flag (a Python int is not a "32-bit" number, it's an arbitrary-precision integer, with a dynamically allocated representation stored in some fashion other than simple 2's complement).

block = '10101010001000101110101000101110'
asnum = int(block, 2)
if block[0] == '1':
    asnum ^= 0xFFFFFFFF
    asnum += 1
    asnum = -asnum

print(asnum)
like image 28
aghast Avatar answered Jan 19 '26 15:01

aghast



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!