Search code examples
pythonstringlistbitmultiplication

Function is supposed to multiply 2 binary numbers (without special functions), but it isn't


Here is function which takes 2 binary numbers(str) in form of 8 signs(for example 4=00000100). in formula, we have to reverse second number and for each bit separately do next actions:

  1. If it is 1, then we add 1st binary number to high register, than we add as first number 1 if we had overcrowding or 0 if we didn't, than we take last number in high register and put it into 1st number of low register, afterwards we delete last element in low register.
  2. If bit is 0, we just add 0 in beginning of high register(HG), add the last number of HG and put it into 1st number of (LG) and del last bits in HG and LG. Then we just put HG and LG together and get result.

looks like: 3*4 = 12: 00000011(bin1) * 00000100(bin2) = 00000000 00001100 (result) steps: we take reversed bin2 and observe each bit

  1. the first = 0: so mid-result = 00000000 00000000, same for 2nd since it = 0
  2. bit = 1, we summarize bin1 and 00000000 = 00000011, mid-res = 00000001 10000000
  3. bit = 0 so mid-res = 00000000 11000000. final: 00000000 00001100

Please, I would be very grateful for any help, I'm really struggling with this task.

def result_first_diapazone(bin1, bin2): 
    carry = 0
    elder_result_list = ['0', '0', '0', '0', '0', '0', '0', '0'] 
    younger_result_list = ['0', '0', '0', '0', '0', '0', '0', '0'] 
    bin1_list = list(reversed(bin1))
    bin2_list = list(reversed(bin2))

    for bit in bin2_list:
        if bit == '1':
            for i, (x, y) in enumerate(zip(bin1_list, reversed(elder_result_list))):
                if (x, y) == ('0', '0') and carry == 0:
                    elder_result_list[i] = '0'
                    carry = 0
                elif (x, y) == ('0', '0') and carry == 1:
                    elder_result_list[i] = '1'
                    carry = 0
                elif (x, y) == ('1', '0') and carry == 0:
                    elder_result_list[i] = '1'
                    carry = 0
                elif (x, y) == ('1', '0') and carry == 1:
                    elder_result_list[i] = '0'
                    carry = 1
                elif (x, y) == ('0', '1') and carry == 0:
                    elder_result_list[i] = '1'
                    carry = 0
                elif (x, y) == ('0', '1') and carry == 1:
                    elder_result_list[i] = '0'
                    carry = 1
                elif (x, y) == ('1', '1') and carry == 0:
                    elder_result_list[i] = '0'
                    carry = 1
                elif (x, y) == ('1', '1') and carry == 1:
                    elder_result_list[i] = '1'
                    carry = 1
                else:
                    elder_result_list[i] = '1'
                    carry = 1
            elder_result_list.append(str(carry))
            elder_result_list.pop(0)
        else:
            elder_result_list.append('0')
            elder_result_list.pop(0)
    elder_result_list = reversed(elder_result_list)
    elder_result_str = ''.join(map(str, elder_result_list))
    younger_result_str = ''.join(map(str, younger_result_list))
    result_result = elder_result_str + ' ' + younger_result_str
    return result_result

I tried to change this code but it is correct as it seems to me according to logic which I wrote before.


Solution

  • You have lots of problems with your code:

    1. You are not using: younger_result_list. This is supposed to hold the low order result.
    2. You iterate in reverse over elder_result_list, but are updating it using forward indexes.
    3. The lines: elder_result_list.pop(0) is removing results from the wrong end.

    I have rewritten it like this where I use a temporary list result_list to hold the results of the addition and I remove the correct bit from elder_result_list and add it to younger_result_list:

    def result_first_diapazone(bin1, bin2):
        carry = 0
        elder_result_list = ['0', '0', '0', '0', '0', '0', '0', '0']
        younger_result_list = []
        bin1_list = list(reversed(bin1))
        bin2_list = list(reversed(bin2))
    
        for bit in bin2_list:
            if bit == '1':
                result_list = []
                for i, (x, y) in enumerate(zip(bin1_list, reversed(elder_result_list))):
                    if (x, y) == ('0', '0') and carry == 0:
                        result_list.append('0')
                        carry = 0
                    elif (x, y) == ('0', '0') and carry == 1:
                        result_list.append('1')
                        carry = 0
                    elif (x, y) == ('1', '0') and carry == 0:
                        result_list.append('1')
                        carry = 0
                    elif (x, y) == ('1', '0') and carry == 1:
                        result_list.append('0')
                        carry = 1
                    elif (x, y) == ('0', '1') and carry == 0:
                        result_list.append('1')
                        carry = 0
                    elif (x, y) == ('0', '1') and carry == 1:
                        result_list.append('0')
                        carry = 1
                    elif (x, y) == ('1', '1') and carry == 0:
                        result_list.append('0')
                        carry = 1
                    elif (x, y) == ('1', '1') and carry == 1:
                        result_list.append('1')
                        carry = 1
                    else:
                        result_list.append('1')
                        carry = 1
                result_list.append(str(carry))
                elder_result_list = list(reversed(result_list))
            else:
                elder_result_list.insert(0,'0')
            low = elder_result_list.pop()
            younger_result_list.append(low)
    
        elder_result_str = ''.join(map(str, elder_result_list))
        younger_result_str = ''.join(map(str, reversed(younger_result_list)))
        result_result = elder_result_str + ' ' + younger_result_str
        return result_result
    

    Sample code to calculate 42*42=1764:

    result = result_first_diapazone('00101010', '00101010')
    print(result)
    

    Output:

    00000110 11100100
    

    Update:

    addition_table = {
        ('0', '0', '0'): ('0', '0'),
        ('0', '0', '1'): ('1', '0'),
        ('0', '1', '0'): ('1', '0'),
        ('0', '1', '1'): ('0', '1'),
        ('1', '0', '0'): ('1', '0'),
        ('1', '0', '1'): ('0', '1'),
        ('1', '1', '0'): ('0', '1'),
        ('1', '1', '1'): ('1', '1')
    }
    
    
    def binary_add(augend, addend):
        result = ['0'] * 8
        carry = '0'
        for i, (x, y) in enumerate(zip(augend, addend)):
            result[i], carry = addition_table[(x, y, carry)]
        return result, carry
    
    
    def binary_multiply(multiplier, multiplicand):
        upper_result_list = ['0'] * 8
        lower_result_list = []
    
        for bit in multiplier:
            if bit == '1':
                upper_result_list, carry = binary_add(multiplicand, upper_result_list)
                upper_result_list.append(carry)
            else:
                upper_result_list.append('0')
    
            low = upper_result_list.pop(0)
            lower_result_list.append(low)
        return upper_result_list, lower_result_list
    
    def l_r(i):
        return list(reversed(i))
    
    def result_first_diapazone(multiplier, multiplicand):
        upper, lower = binary_multiply(l_r(multiplier), l_r(multiplicand))
        return ''.join(reversed(upper))+ ' ' + ''.join(reversed(lower))
    

    Output as above.

    Note that my first code sample gives the wrong output in certain cases because the carry variable is defined too early. It should be inside the first for loop, not at the start. My updated code gets it right since it is part of the binary_add() function.