0

I implemented one's complement addition of 16 bit integers in python, however I am trying to see if there is a better way to do it.

 # 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

And now an example of running it would be:

print add_bits("1010001111101001", "1000000110110101")

returns :

0010010110011111

Is what wrote safe as far as results (Note I didn't do any negation here since that part is trivial, I am more interested in the intermediate steps)? Is there a better pythonic way to do it? Thanks for any help.

4

2 回答 2

5

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

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
于 2015-04-24T09:25:29.720 回答
1

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

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


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

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

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


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


因此,坚持您的基本设计“对位使用字符串,仅使用从 Python 1.5 到 3.5 未更改的基本字符串操作而不是format,并对整数而不是位进行基本加法”,我会写成这样:

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))

但更好的解决方案是完全抽象出字符串表示。构建一个知道如何表现得像整数的类,但也知道如何表现得像位序列。或者只是在 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 上有六个不同的位操作库,它们都有不同的接口和不同的优缺点;我刚刚选择了在搜索中出现的第一个,并使用它拼凑了一个实现。

于 2015-04-24T08:50:12.067 回答