Python:16 位补码加法实现

Python:16 bit one's complement addition implementation

我在 python 中实现了 16 位整数的补码加法,但是我正在尝试看看是否有更好的方法。

 # This function returns a string of the bits (exactly 16 bits)
 # for the number (in base 10 passed to it)
 def get_bits(some_num):
        binar = bin(some_num)[2::]
        zeroes = 16 - len(binar)
        padding = zeroes*"0"
        binar = padding + binar
        return binar


# This function adds the numbers, and handles the carry over
# from the most significant bit
def add_bits(num1, num2):
        result = bin(int(num1,2) + int(num2,2))[2::]
        # There is no carryover
        if len(result) <= 16 :
                result = get_bits(int(result,2))
        # There is carryover
        else :
                result = result[1::]
                one = '0000000000000001'
                result = bin(int(result,2) + int(one,2))[2::]
                result = get_bits(int(result,2))
        return result

现在 运行 的一个例子是:

print add_bits("1010001111101001", "1000000110110101")

returns :

0010010110011111

就结果而言,写的是安全的吗(请注意,我在这里没有做任何否定,因为那部分是微不足道的,我对中间步骤更感兴趣)?有更好的 pythonic 方法吗? 感谢您的帮助。

在数字、一位字符串列表和字符串之间来回转换可能不像是一种非常 Pythonic 的入门方式。

更具体地说,使用 bin(i)[2:] 将一个 int 转换为一个位序列是非常 hacky 的。无论如何,这可能是值得做的(例如,因为它比数字更简洁或更有效),但即使是这样,最好将它包装在一个以其功能命名的函数中(甚至可能添加注释解释你为什么那样做)。


您还有不必要的复杂代码。例如,要进行进位,您可以这样做:

one = '0000000000000001'
result = bin(int(result,2) + int(one,2))[2::]

但是你知道 int(one,2) 只是数字 1,除非你搞砸了,所以为什么不直接使用 1,它更短、更易读、更明显, 并消除任何搞砸的机会?


而且您没有遵循 PEP 8 风格。


所以,坚持你 "use a string for the bits, use only the basic string operations that are unchanged from Python 1.5 through 3.5 instead of format, and do the basic addition on integers instead of on the bits" 的基本设计,我会这样写:

def to_bits(n):
    return bin(n)[2:]

def from_bits(n):
    return int(n, 2)

def pad_bits(b, length=16):
    return ["0"*length + b][-length:]

def add_bits(num1, num2):
    result = to_bits(from_bits(num1) + from_bits(num2))
    if len(result) <= 16: # no carry
        return pad_bits(result)
    return pad_bits(to_bits(from_bits(result[1:]) + 1))

但更好的解决方案是完全抽象出字符串表示。构建一个 class,它知道如何像整数一样工作,但也知道如何像位序列一样工作。或者只是在 PyPI 上找到一个。然后你的代码变得微不足道。例如:

from bitstring import BitArray

def add_bits(n1, n2):
    """
    Given two BitArray values of the same length, return a BitArray
    of the same length that's the one's complement addition.
    """
    result = n1.uint + n2.uint
    if result >= (1 << n1.length):
        result = result % n1.length + 1
    return BitArray(uint=result, length=n1.length)

我不确定 bitstring 实际上是您正在做的事情的最佳模块。 PyPI 上有六种不同的位操作库,它们都有不同的接口和不同的优缺点;我刚刚选择了搜索中出现的第一个,并使用它拼凑了一个实现。

在字符串和整数之间来回转换以进行数学计算效率低下。用整数进行数学运算并使用格式显示二进制:

MOD = 1 << 16

def ones_comp_add16(num1,num2):
    result = num1 + num2
    return result if result < MOD else (result+1) % MOD

n1 = 0b1010001111101001
n2 = 0b1000000110110101
result = ones_comp_add16(n1,n2)

print('''\
  {:016b}
+ {:016b}
------------------
  {:016b}'''.format(n1,n2,result))

输出:

  1010001111101001
+ 1000000110110101
------------------
  0010010110011111