XTImpossible XTImpossible - 7 months ago 9
Python Question

What is wrong with this alternative bitwise operator function?

n1 = "0b1110"
n2 = "0b101"

def bitwise_or(num1, num2):
diff1 = ""
new_num1 = []
new_num2 = []
new_num = []
for c in num1:
new_num1.append(c)
for c in num2:
new_num2.append(c)
if len(num1) != len(num2):
if len(num1) > len(num2):
diff1 = "0" * (len(num1) - len(num2))
for c in diff1:
new_num2.append(c)
if len(num1) < len(num2):
diff1 = "0" * (len(num2) - len(num1))
for c in diff1:
new_num1.append(c)
for i in range(len(new_num1)):
if new_num1[i] == "1" or new_num2[i] == "1":
new_num.append("1")
else:
new_num.append(new_num1[i])
final = "".join(new_num)
return final

print(bitwise_or(n1,n2))


I made a function that should replicate the | operation, however it's not working correctly. The correct answer was suppose to print out 0b1111, but I don't understand how it gets that.

Answer

When you pad the zeros you should insert them before the bits of the number.

0b1 means the number 1. If you try to or it with 0b11101 you cannot change it to 0b10000 you have to pad it as 0b00001.

Also your handling of 0b works but isn't clear not readable. It just "happen" to work because when you loop through 0b11101 and 0b00001 the first character is 0 in both and so you end up in new_num.append(new_num1[0]) and then b != '1' and hence the if test fails and the b gets inserted in new_num.

I suggest you simply remove the prefix at the beginning and add it at the end. This also slightly simplifies correct padding.


By the way: to convert a string to a list of characters you can simply call list on it:

new_num1 = list(num1)

Moreover to add a certain number of elements to a list you can use the extend method, or you could use slice assignment:

>>> my_list = list('hello')
>>> my_list
['h', 'e', 'l', 'l', 'o']
>>> my_list.extend('world')
>>> my_list
['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']

So your code would become somewhat like this:

def bitwise_or(num1, num2):
    new_num1 =list(num1)
    new_num2 = list(num2)
    if len(num1) > len(num2):
        new_num2[2:2] = '0' * (len(num1) - len(num2))
    elif len(num1) < len(num2):
        new_num1[2:2] = '0' * (len(num2) - len(num1))

    new_num = []
    for c1, c2 in zip(new_num1, new_num2):
        if c1 == "1" or c2 == "1":
            new_num.append("1")
        else:
            new_num.append(c1)
    return ''.join(new_num)

However I'd rather make explicit the handling of the prefix:

def bitwise_or(num1, num2):
    new_num1 =list(num1[2:])
    new_num2 = list(num2[2:])
    if len(num1) > len(num2):
        new_num2[:0] = '0' * (len(num1) - len(num2))
    elif len(num1) < len(num2):
        new_num1[:0] = '0' * (len(num2) - len(num1))

    new_num = []
    for c1, c2 in zip(new_num1, new_num2):
        if c1 == "1" or c2 == "1":
            new_num.append("1")
        else:
            new_num.append(c1)
    return '0b' + ''.join(new_num)