Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Bitwise Slicing
#1
Hi - New to Python so please forgive any mistakes

I want to know if there is a more elegant way of slicing a byte?

I have an 8 bit result from reading a Port Expander (4 MSB's are where my inputs are connected)
In_1, In_2, In_3, In_4 will be used in the main program

def input_status(result):
    #gets a byte value and returns input status
    result = result | 15       # mask out the bottom 4 bits (not really needed)
    result = result >>4        #only interested in the 4 MSBs
    In_1 = result & 1          #check bit 0
    result = result >>1        #shift 1 place right
    In_2 = result & 1          #check bit 1
    result = result >>1        #shift 1 place right
    In_3 = result & 1          #check bit 2
    I_result = result >>1      #shift 1 place right
    In_4 = I_result & 1        #check bit 3
    return (In_1, In_2, In_3, In_4)
This works fine, but seems like a very cumbersome way of doing things?

I was looking for some sort of alias command where I could specify that In_1 = result.4 or something similar but I've not been able to find one.

Thanks for the help - still at the bottom of the learning curve Cool
Reply
#2
I spent ~20 minutes trying to come up with something more elegant, and I believe I've failed:
def f(result):
    return tuple(int(result & 2**x > 1) for x in range(4, 8))

def f2(result):
    result = result >> 4
    return tuple(result >> x & 1 for x in range(4))

def f3(result):
    return tuple(result >> x & 1 for x in range(4, 8))

def f4(result):
    return tuple(int(digit) for digit in f"{(result >> 4) & 15:04b}"[::-1])
Solutions I gave up on but tried include using reduce() and recursion.
Reply
#3
I think the bitwise operators are the way to go. But you *could* print out the binary representation string and then index into it.

result = 231   # high bits are "1110"
bits = [1 if x == "1" else 0 for x in f"{result:08b}"[-8:]] # takes only 8 LSB in case result > 2**8
for i in range(4):
    print(bits[i])
Output:
1 1 1 0
Reply
#4
Ok - thanks for that. Good learning for me - I'm still not fully conversant with the way Python handles data (I'm used to PIC programming - where I can break everything down to the bit level.

If I went with
bits = [1 if x == "1" else 0 for x in f"{result:08b}"[-8:]] # takes only 8 LSB in case result > 2**8
Would that not simply leave me with a string called 'bits' - so effectively just masking out the lower 4 bits of result?

I need to be able to access and act on individual bit values (input is On or Off)

Thanks again
Reply
#5
def bits(value, size=32):
    bit_values = []
    for bit in range(size):
        bit_values.insert(0, value & 1)
        value = value >> 1
    return bit_values

print(bits(42, 8))

def bitslice(value, start, end):
    retvalue = 0
    for bit in range(start, end+1):
        retvalue += (value & 1 << bit) >> start
    return retvalue

print(bitslice(42, 1, 5), bits(bitslice(42, 1, 5), 5))

def bit(value, index):
    return (value & 1 << index) >> index

print([bit(42, i) for i in range(8)])

def setbit(value, bit):
    return value | 1 << bit

def clrbit(value, bit):
    mask = 1 << bit
    if value & mask == 0:
        return value
    return value ^ mask

print(setbit(5, 1), clrbit(7, 1))
Reply
#6
(Aug-25-2020, 03:00 AM)Peter_Truman Wrote: If I went with
bits = [1 if x == "1" else 0 for x in f"{result:08b}"[-8:]] # takes only 8 LSB in case result > 2**8
Would that not simply leave me with a string called 'bits' - so effectively just masking out the lower 4 bits of result?

No, it's just compact. The first part (the f-string) converts the byte to the 8 LSB bits as a string object. f"{result:08b}"[-8:]

The next part goes through each character of the string one-by-one and converts it to a list of numbers, either 0 or 1. So the MSB is index 0 and the LSB is index 7, via a list comprehension. Expanding the loop, it would look like:

temp_list = []
for x in f"{result:08b}"[-8:]:
    if x == "1":
        temp_list.append(1)
    else:
        temp_list.append(0)
bits = temp_list
So at the end, you've got the list [1, 1, 1, 0, 0, 1, 1, 1]

It looks like there's also a PyPi module called bitstring. It could be that it has some functions that would be useful.
Reply
#7
Thanks to all - the bitstring module looks much more natural to my eyes. I'll give this all a whirl in the morning.

Cheers
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Program demonstrates operations of bitwise operators without using bitwise operations ShawnYang 2 1,782 Aug-18-2021, 03:06 PM
Last Post: deanhystad
  Bitwise ~ Operator muzikman 10 3,933 Feb-07-2021, 04:07 PM
Last Post: muzikman
  not bitwise ~15 1885 3 2,501 Oct-30-2019, 03:49 AM
Last Post: 1885
  understanding exponential and bitwise operators srm 1 2,044 Jun-15-2019, 11:14 AM
Last Post: ThomasL

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020