基数为-2的二进制数加法

213 阅读4分钟

学习笔记:基数为-2的二进制数加法

1. 背景概念

在数字系统中,我们通常遇到的是基数为正数的系统,比如十进制(基数为10)和二进制(基数为2)。然而,也存在一些较为特殊的数字表示法,其中之一就是基数为-2的二进制数表示法。

基数为-2的二进制系统是一种特殊的数值表示方式,其权重是基数-2的幂次。例如,如果数组arr = [1, 1, 0, 1],它代表的值就是:

1×(−2)3+1×(−2)2+0×(−2)1+1×(−2)0=−8+4+0+1=−31 \times (-2)^3 + 1 \times (-2)^2 + 0 \times (-2)^1 + 1 \times (-2)^0 = -8 + 4 + 0 + 1 = -31×(−2)3+1×(−2)2+0×(−2)1+1×(−2)0=−8+4+0+1=−3

与常规的二进制不同,在基数为-2的系统中,权重呈现交替的正负变化,这使得相同的位数组合可以表示正负值,而不需要额外的符号位。

2. 问题描述

我们需要将两个基数为-2的二进制数相加,给出它们相加后的结果数组形式。这个问题涉及如何正确处理位数进位和负进位的情况,并确保结果中不含前导零。

3. 思路分析

基数为-2的加法与普通的二进制加法类似,但由于基数为负,我们需要处理特别的进位和借位情况:

  • 逐位相加:我们从最低位开始逐位相加,同时考虑进位。

  • 特殊的进位规则

    • 当相加的结果等于2时,我们需要向左进一位,同时当前位结果为0
    • 当相加的结果为-1时,这表示需要向左边借位,因此我们将当前位设为1,并将进位设置为1(即向左边借一个-2的权重)。

4. Python 实现

以下是用 Python 编写的 solution 函数,用于解决这个问题:

python
复制代码
def solution(arr1, arr2):
    i, j = len(arr1) - 1, len(arr2) - 1
    carry = 0
    result = []
    
    # 处理所有的位直到没有更多的数字和进位需要处理
    while i >= 0 or j >= 0 or carry != 0:
        # 如果超出了数组的范围,则默认为0
        x = arr1[i] if i >= 0 else 0
        y = arr2[j] if j >= 0 else 0
        
        # 计算当前位和之前位的进位的总和
        sum = x + y + carry
        
        # 计算当前位置应有的值,加入结果中
        if sum == -1:
            result.append(1)
            carry = 1  # 负进位,实际上是向更高位借位
        else:
            result.append(sum % 2)
            carry = -(sum // 2)
        
        # 移动索引向更高的位
        i -= 1
        j -= 1
    
    # 去掉结果中的前导零,除非结果本身为零
    while len(result) > 1 and result[-1] == 0:
        result.pop()
    
    # 因为结果是从低位到高位构建的,返回前需要反转
    return result[::-1]

# 测试样例
print(solution([1,1,1,1,1], [1,0,1]))  # 输出:[1, 0, 0, 0, 0]
print(solution([1,0,0], [1,1,1]))  # 输出:[1, 1, 0, 1, 1]
print(solution([0], [0]))  # 输出:[0]

5. 代码详解

  • 初始化

    • 使用 ij 分别指向 arr1arr2 的最后一位,carry 用于存储进位。
    • result 用于存储相加后的结果,最后需要反转返回。
  • 逐位相加

    • 对于每个位,取出 arr1[i]arr2[j] 的值(如果超出范围则取 0),将它们和 carry 相加,得到 sum
    • 对于 sum,计算当前位的值,加入 result 数组中,同时更新 carry
  • 处理进位和借位

    • sum 等于 -1 时,我们需要借位,当前位设为 1,同时将 carry 设为 1
    • 对于其他的情况,通过 sum % 2 得到当前位,-(sum // 2) 计算进位的方向和大小。
  • 去除前导零

    • 在得到最终结果后,我们需要去除前导零,但至少保留一个零(如果结果是0)。
  • 返回结果

    • 由于结果是从低位到高位依次添加的,因此需要反转才能得到最终正确的结果。

6. 总结

基数为-2的二进制加法是一个较为特殊的计算问题,主要挑战在于处理不同的进位和借位规则。通过逐位相加、处理进位和借位,我们能够正确地计算两个基数为-2的二进制数的和。在解决这类问题时,我们学习了如何通过不断取模和调整进位来实现一个复杂的进制运算,这对于理解其他特殊进制系统的运算有很大的帮助。

这种问题不仅加深了我们对进制运算的理解,也让我们对编程中的逻辑运算、进位处理有了更深入的认识。通过这种练习,我们可以更好地理解如何在不同的数字系统下进行加法操作,并掌握如何设计合理的算法来处理进位和借位。