如何在Python中用模拟逻辑门实现正确的二进制减法?
修复二进制减法的逻辑问题
你的代码存在三个核心问题:逻辑门的方法定义错误、全减器的借位计算逻辑不正确,以及多余的最高位处理步骤。以下是具体修复方案:
1. 修正逻辑门的方法定义
你的逻辑门execute方法未使用静态方法装饰器,直接通过类调用时会把类本身作为第一个参数传入,导致参数匹配错误。需要给每个门的execute方法添加@staticmethod:
class ANDGate: @staticmethod def execute(a, b): result = "" for bit_a, bit_b in zip(a, b): result += '1' if bit_a == '1' and bit_b == '1' else '0' return result class ORGate: @staticmethod def execute(a, b): result = "" for bit_a, bit_b in zip(a, b): result += '1' if bit_a == '1' or bit_b == '1' else '0' return result class XORGate: @staticmethod def execute(a, b): result = "" for bit_a, bit_b in zip(a, b): result += '1' if (bit_a == '1' and bit_b == '0') or (bit_a == '0' and bit_b == '1') else '0' return result class NOTGate: @staticmethod def execute(a): result = "" for bit_a in a: result += '0' if bit_a == '1' else '1' return result
2. 修正减法函数的全减器逻辑
全减器的借位输出(borrow_out)公式错误,正确的借位逻辑应该是:borrow_out = (NOT a AND b) OR (NOT a AND borrow_in) OR (b AND borrow_in)
同时需要移除多余的最高位处理步骤——循环已经覆盖了所有位的计算,额外处理会破坏正确结果。
修复后的subtract函数:
def subtract(a, b): result = "" borrow = '0' max_len = max(len(a), len(b)) # 给较短的操作数补前导零 a = a.zfill(max_len) b = b.zfill(max_len) for bit_a, bit_b in zip(reversed(a), reversed(b)): # 计算当前位差值:a XOR b XOR 输入借位 diff = XORGate.execute(XORGate.execute(bit_a, bit_b), borrow) # 计算新的借位:(NOT a AND b) OR (NOT a AND 输入借位) OR (b AND 输入借位) not_a = NOTGate.execute(bit_a) term1 = ANDGate.execute(not_a, bit_b) term2 = ANDGate.execute(not_a, borrow) term3 = ANDGate.execute(bit_b, borrow) borrow = ORGate.execute(ORGate.execute(term1, term2), term3) result = diff + result print(f"bit_a: {bit_a}, bit_b: {bit_b}, diff: {diff}, borrow: {borrow}, result: {result}") # 去除前导零,若结果全为零则保留一个零 result = result.lstrip('0') or '0' return result
3. 测试验证
调用subtract('101010', '1100')会得到正确结果11110,调试输出的借位传递过程如下:
bit_a: 0, bit_b: 0, diff: 0, borrow: 0, result: 0 bit_a: 1, bit_b: 0, diff: 1, borrow: 0, result: 10 bit_a: 0, bit_b: 1, diff: 1, borrow: 1, result: 110 bit_a: 1, bit_b: 1, diff: 1, borrow: 1, result: 1110 bit_a: 0, bit_b: 0, diff: 1, borrow: 1, result: 11110 bit_a: 1, bit_b: 0, diff: 0, borrow: 0, result: 011110
最终去除前导零后得到11110,与预期一致。
内容的提问来源于stack exchange,提问作者TheCodingGolfer
相关产品推荐
相关产品推荐

