an easy way to choose bit(s) form a word - python

Is there an easy way to choose bit(s) form a word ?
I prefer to use with built in library.
For example,
I read the data from binary file (I read 32bit each time because I work with words)
num = 128 (1000 0000 )
I want: num[7:6] = 10 in binary = 2
I did it with ('shift' and 'and') or int(bin(128)[2:][::-1][6:8][::-1],2)

You could use bitwise operators. e.g,
(((1 << 8) - 1) & num) >> 6
In general, for bits a to b (higher bits to lower, 0-indexed),
(((1 << (a+1)) - 1) & num) >> b
Explanation:
Say num is 121 = 0111 1001, and we want bit 4 to bit 2 (0-indexed). i.e, 110 or 6. So a = 4, b = 2.
((1 << (a+1)) - 1) is just 111...a times. Doing & with this helps us pick the last "a" bits. e.g, any number & 11 will pick its last 2 bits. A number & 111 will pick the last 3 and so on.
So ((1 << (a+1)) - 1) & num is just the last a bits of num.
>> b drops the last b bits.
Therefore, together,
(((1 << (a+1)) - 1) & num) >> b has the effect of picking the last a bits from num, then dropping the last b bits. So together, it will return bits in the a to b range

Related

Left shift but replace the shifted bits with ones

In Python the << operator does the following:
Returns x with the bits shifted to the left by y places (and new bits on the right-hand-side are zeros). This is the same as multiplying x by 2**y.
I want to have another version where it fills 1 on the new bits. Is there a built in function for this, if not how do I write it?
Is x = (x << y) | ((1 << y) - 1) what you're looking for?
First, we shift x left y bits:
x = 21
y = 2
bin(x) == 10101 (in binary)
x << y == 1010100
Then, the number ((1 << y) - 1) gives us a number with only the y lowest bits set to 1,
e.g.
1 << 2 == 100
(1 << 2) - 1 == 011
Finally, we or them to get 1010100 | 11 == 1010111.
There's no such function built in, or, for that matter, available in any extension library I know of.
It's pretty easy to do yourself, though. Say the int is n and you want to shift it left by s bits.
First flip all the bits of n (change all 0 bits to 1, and all 1 bits to 0). Then shift left by s. That adds s 0 bits on the right. Then flip the bits again. The new trailing 0 bits are changed to 1 bits, and the original bits of n are restored.
>>> n = 5
>>> bin(n)
'0b101'
>>> ~(~n << 6)
383
>>> bin(_)
'0b101111111'

Python binary opposite operations

I have two numbers:
num1 = 1
num2 = 1
And then someone applied a secret operation on them:
mask = 2**8 -1
secret = (num1 << 8) | (num2 & mask)
>>> 257
How can I do the opposite of the secret operation? to get from 257 to 1 1
this is a standard way of encoding 2 small integers into a larger one
its 16bits of data representing 2 8 bit integers
to get the first one (upper 8 bits) back you shift it the other way
256 >> 8
to get the lower 8 bits just and it with the original mask
256 & (2**8-1)
as mentioned in the comments most ints are int32 (32 bits, not 8) and you likely cannot recover num2 if its value was greater than 255, because 8 bits can only represent 0-255
as an aside I imagine most people would use (1<<8)-1 instead of 2**8-1

Getting a specific group of binary numbers in an Int?

If I am trying to get a specific range of bits (in decimal) at a specific range, is the best way to go about this leftshifting to the end index, and then right shifting back to the start index?
#pesudo-code:
def group(aNumber,start, end):
n = aNumber << 32 - n
a = n >> end - start
print(a)
You can do that in python, you're just not using the correct method. When you want to retrieve part of a number, the operation you're trying to accomplish is called masking.
And you do that with a mask: number & 0xF0 will retreive bits 4 to 7 (without moving them).
So (number & 0xF0) >> 4 will retrieve bits 4 to 7, and shift them all the way to the right.
As for the mask, ((1 << end) - 1) - ((1 << start) - 1) should build a correct mask. So...
mask = ((1 << end) - 1) - ((1 << start) - 1)
result = (number & mask) >> start
Actually, since you shift to the right right after, you don't even have to mask out the bits below those you want, so this will work just as well:
mask = ((1 << end) - 1)
result = (number & mask) >> start
If you want to get from bit b0 a total of bn bits:
def getbits(x, b0, bn):
return (x >> b0) & ((1 << bn) - 1)

Variable assignment with ">>" and "&" operators

I've been trying to understand a Python script and I can't figure out what this assignment is doing:
data_byte2 = value >> 7 & 127
I've seen a kind of similar construct with the or operator but never with & and I have no idea at all what >> does (nothing's coming up on Google for it).
value >> 7 & 127
Is like writing:
(value >> 7) & 127 # see Python Operators Precedence
First you rightshift value by 7, then & result with 127.
127 in binary is 1111111, when you & with this number, you're clearing all bits on left of the number. For example, if you have 16 bit number:
1101011101111101
→
Shifting it 7 to the right will result in:
0000000110101110
& with 127 will keep only most right 8 bits:
0000000110101110
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
0000000001111111 & (127)
----------------
0000000000101110
>> is the right bit-shift operator, and & is bitwise AND.
This is easier to see if you look at numbers in binary form.
>>> format(13, "08b")
'00001101'
>>> format(13 >> 1, "08b")
'00000110'
You can see that the binary digits are right-shifted by one place (this is equivalent to a division by 2, so x >> y is equivalent to x // (2 ** y)). On that basis, x >> 7 means "shift x's bits seven places to the right", or "divide x by 128".
>>> format(10, "08b")
'00001010'
>>> format(7, "08b")
'00000111'
>>> format(10 & 7, "08b")
'00000010'
Here the output includes a 1 for every bit where both inputs have 1, 0 otherwise. Given that
>>> format(127, "08b")
'01111111'
x & 127 means "take the last seven bits of x".
As >> has higher operator precedence than &, the expression
value >> 7 & 127
means "divide value by 128 then take the last seven bits".
>> is right shift operator
>>> 3 >> 1
1
binary of 3 is 00011, now shift one bit towards right the so it will be 00001 so we get answer 1
>>> 3 >> 2
0
binary of 3 is 00011, now shift two bit towards the right, so it will be 0000, so output is 0

Complement of XOR

What is the most efficient algorithm for finding ~A XOR B? (Note that ~ is the complement function, done by reversing each 1 bit into 0 and each 0 into 1 bit, and XOR is the exclusive or function)
For example, ~4 XOR 6 = ~010 = 101 = 5 and ~6 XOR 9 = ~1111 = 0
Here's an answer that takes into account the number of bits needed to store your integers:
def xnor(a, b):
length = max(a.bit_length(), b.bit_length())
return (~a ^ b) & ((1 << length) - 1)
I can't think of a situation where this is better than just ~a ^ b however. And it almost certainly makes no sense for negative numbers.
The only problem here is that ~ returns a negative number for a positive input, and you want a positive result limited to the significant bits represented in the inputs.
Here's a function that can generate a mask of bits that are needed in the result:
def mask(n):
n = abs(n)
shift = 1
while n & (n + 1) != 0:
n |= n >> shift
shift *= 2
return n
And here's how to use it:
print (~a ^ b) & mask(a | b)
You can simply use ==.
A XNOR B is same as == operator because:
A B NXOR
F F T
F T F
T F F
T T T

Categories

Resources