0

Challenge:

I would like to write a method which would take

  1. INTEGER value
  2. START_BIT
  3. Number of bits to be replaced after the START_BIT
  4. REPLACING_BIT (boolean)

Return: the modified value based on the inputs.

Input Example:

  • Decimal: 255 or in Binary: 11111111

Expected output:

  • Decimal: 227 or in Binary: 11100011

i.e 3 bits are replaced with ZEROS starting from second bit position.

Current code:

def set_bit(original_int:int, start_bit_pos:int, number_of_bits:int, bit_value:bool):
    if number_of_bits < 1: number_of_bits = 1
        
    out = original_int
    for i in range(number_of_bits):
        if bit_value == 1:
            out = out | (1<<(start_bit_pos+i))
        else:
            out = out & ~(1<<(start_bit_pos+i))
    print('old binary: '+ '{:b}'.format(original_int),f' Decimal: {original_int}' )
    print('new binary: '+ '{:b}'.format(out), f' Decimal: {out}' )
    return out

set_bit(original_int = 255, start_bit_pos= 2, number_of_bits = 3, bit_value = 0)
set_bit(original_int = 64, start_bit_pos= 2, number_of_bits = 3, bit_value = 1)

Current issue:

The above code is functional, however I do feel it is an overkill, so I wonder if there is a standard python function which could do a similar thing?

2 Answers 2

3
  • A sequence of 1 bits is 1.
  • A sequence of 2 bits is 11 or decimal 3.
  • A sequence of 3 bits is 111 or decimal 7.
  • A sequence of N bits is 2^N-1, which is the same as (1 << N) - 1.

You have to also shift that to the left if the starting position is not 0.

Therefore, you can simply do this:

def set_bit(original_int:int, start_bit_pos:int,
            number_of_bits:int, bit_value:bool):
    mask = (1 << number_of_bits) - 1 << start_bit_pos
    if bit_value:
        return original_int | mask
    return original_int & ~mask
Sign up to request clarification or add additional context in comments.

Comments

1

Here is a function that can update an arbitrary number of bits at an arbitrary location in an arbitrary word size. Here x is the original integer, start_bit is the location of first insertion, starting from 0 from the right (least significant bit), field_size is the number of bits to replace, and val is the value to plug into the field. word_size should reflect the number of bits expected in x

def apply_bits(x, start_bit, field_size, val, word_size=8):
    
    print("x=",bin(x))
    
    mask = 2**word_size - 1 - (2**field_size -1) * (2**start_bit)
    print("mask=",bin(mask))
    
    val = min(val, 2**(field_size) - 1)
    print("val=", bin(val))
    
    w = val * 2**start_bit
    
    print("w=",bin(w))
        
    y = (x & mask) | w
    print("y=",bin(y))
    
    return(y)

for example:

>>> apply_bits(x=0b10000001,start_bit=2,field_size=4,val=0b1010,word_size=8)
   x= 0b10000001
 val= 0b1010
mask= 0b11000011
   w= 0b101000
   y= 0b10101001

and

apply_bits(x=0b10101010101010101,start_bit=4,field_size=8,val=0b11100111,word_size=16)
   x= 0b10101010101010101
 val= 0b11100111
mask= 0b1111000000001111
   w= 0b111001110000
   y= 0b101111001110101

First the function makes a mask of zeros at the location of the field. Then the value is constrained to fit into the field size and shifted into position. Finally the field is zero-ed out using bitwise-and, and the new values are put in using bitwise-or. The print statements let you follow along the process.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.