Converting bitstring to 32-bit signed integer yields wrong result

♀尐吖头ヾ 提交于 2021-02-05 07:22:46

问题


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.


回答1:


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)



回答2:


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



回答3:


You should check for when the input value is out of the positive range for 32 bit signed integers:

res = int(block, 2)
if res >= 2**31:
    res -= 2**32

So first you interpret the number as an unsigned number, but when you notice the sign bit was set ( >= 2^31 ), you subtract 2^32 so to get the negative number.



来源:https://stackoverflow.com/questions/42181229/converting-bitstring-to-32-bit-signed-integer-yields-wrong-result

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!