pythonnumber-systems

converts signed decimal numbers to signed binary and vice versa


Can't Write Decimal To Binary and vice versa converter that works with the positive and negative numbers.

This Decimal To Binary Converter works fine

# decimal to binary 
def to2sCompStr(num):
    bitWidth = 8
    num &= (2 << bitWidth-1)-1 
    formatStr = '{:0'+str(bitWidth)+'b}'
    ret =  formatStr.format(int(num))
    return ret


print(to2sCompStr(-100))
#output 10011100


# Binary To decimal
binary = 10011100 
print(int(binary, 2))
# output 156, not -100
    

Binary To Decimal Working only on positive number, not negative


Solution

  • The call to int function with the base argument set to 2 in order to convert binary strings does not recognize input in two's-complement notation. It cannot assume that the leftmost "bit" (actually a character '0' or '1') of the input string is a sign bit. It does, however, recognize a leading '-' character.

    Therefore, your to2sCompStr needs to negate negative numbers before calling int() and then prefix the result with a '-':

    # decimal to binary
    def to2sCompStr(num):
        bitWidth = 8
        if num < 0:
            negative = True
            num = -num
        else:
            negative = False
        num &= (2 << bitWidth-1)-1
        formatStr = '-{:0'+str(bitWidth)+'b}' if negative else '{:0'+str(bitWidth)+'b}'
        return formatStr.format(int(num))
    
    
    binary = to2sCompStr(-100)
    print(binary)
    #output -01100100
    
    
    print(int(binary, 2))
    # output -100
    

    Prints:

    -01100100
    -100
    

    The alternative is not to use the int builtin function:

    BITWIDTH = 8
    MAX_POSITIVE_NUM = 2 ** (BITWIDTH - 1) - 1
    MIN_NEGATIVE_NUM = -(2 ** (BITWIDTH - 1))
    
    # decimal to binary:
    
    def to2sCompStr(num):
        if not (MIN_NEGATIVE_NUM <= num <= MAX_POSITIVE_NUM):
            raise ValueError(f'Invalid input: {num}')
        num &= (2 << BITWIDTH-1)-1
        formatStr = '{:0'+str(BITWIDTH)+'b}'
        return formatStr.format(int(num))
    
    # binary to decimal:
    
    def strTo2Int(num):
        n = int(num, 2)
        return n if num[0] == '0' else -(2**len(num) - n)
    
    for n in (0, 1, -1, 100, -100):
        base2 = to2sCompStr(n)
        base10 = strTo2Int(base2)
        print(n, base2, base10)
    

    Prints:

    0 00000000 0
    1 00000001 1
    -1 11111111 -1
    100 01100100 100
    -100 10011100 -100