bitwise operation and Two's complement in python

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



bitwise operation and Two's complement in python



I have an array of (short) data which is shifted 4 to left and it is also a signed number. I need to plot it around zero.



for instance: if the number in the array is 0b0000000011111111 and I shift it to left by 4, I will get 0b000000001111. it is fine.


0b0000000011111111


0b000000001111



for instance: if the number in the array is 0b100011111111 and I shift it to left by 4, I will get 0b000010001111. It is fine, but now it is not a negative number.


0b100011111111


0b000010001111



can someone help ?





Your question is not clear. In both instances, you say "shift it to left" but it looks like a shift to the right (toward the least significant bit). Do you mean "shift it to the right"? Also, the problem itself is not clear. Do you want to shift negative numbers and still get a negative number? Also, just how do you do the shifts? What is the data format of the numbers--16 bit integers? What kind of variable is it in?
– Rory Daulton
Aug 8 at 7:24






The only solution I can think of is to convert them to positive numbers before making the shift and then back to negative. This wikipedia page provides a good explanation of how two's compliment works.
– Bill
Aug 8 at 7:25





Python doesn't use two's complement in its integers, 0b10001111111 == 2303.
– jonrsharpe
Aug 8 at 7:25


0b10001111111 == 2303





@ jonrsharpe FYI you're missing a 1 at the end (0b100011111111).
– Bill
Aug 8 at 7:28


1


0b100011111111




3 Answers
3



You have to write your own implementation of the arithmetic right shift of a 16-bit value, if this is what you need. I suggest you this one, very easy to understand:


def arithmetic_right_shift_on_16_bits(val, n):
# Get the sign bit
s = val & 0x8000
# Perform the shifts, padding with the sign bit
for _ in range(n):
val >>= 1
val |= s
return val

a = arithmetic_right_shift_on_16_bits(0b0000000011111111, 4)
print(bin(a)) # 0b1111

b = arithmetic_right_shift_on_16_bits(0b1000000011111111, 4)
print(bin(b)) # 0b1111100000001111



This does not happen in Python:


>>> bin(0b0000000011111111 >> 4) # 15
'0b1111'
>>> bin(0b100011111111 >> 4) # 143
'0b10001111'



BTW, the number you show as an example of a negative short integer is not one, because you gave only 12 bits. So I will assume that the number of interest is 0b1000000011111111. As Python does not use 2's complement, it is shown as 33023. But you can do the 2's complement by hand: for a short int (16 bits), you just substract 0x10000 to the number.


0b1000000011111111


33023



You can then write:


def short_signed_right_shift(x, i):
if x < 0 or x >= 0x10000: raise ValueError # only accept 16 bits numbers
return x >> i if (x < 0x7FFF) else 0x10000 + ((x - 0x10000) >> i)



You can then use it:


>>> bin(short_signed_right_shift(0b0000000011111111, 4))
'0b1111'
>>> bin(short_signed_right_shift(0b1000000011111111, 4))
'0b1111100000001111'






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard