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
我在 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