加密运算

标签: 位运算 数学

难度: Easy

计算机安全专家正在开发一款高度安全的加密通信软件,需要在进行数据传输时对数据进行加密和解密操作。假定 dataAdataB 分别为随机抽样的两次通信的数据量:

  • 正数为发送量
  • 负数为接受量
  • 0 为数据遗失

请不使用四则运算符的情况下实现一个函数计算两次通信的数据量之和(三种情况均需被统计),以确保在数据传输过程中的高安全性和保密性。

示例 1:

输入:dataA = 5, dataB = -1
输出:4

提示:

  • dataA 和 dataB 均可能是负数或 0
  • 结果不会溢出 32 位整数

Submission

运行时间: 32 ms

内存: 14.8 MB

class Solution:
    def add(self, a: int, b: int) -> int:
        x = 0xffffffff
        a &= x
        b &= x
        while b != 0:
            carry = (a & b) << 1 & x  # 无进位的和为异或值,进位为与操作左移1位;
            total = a ^ b
            a = total
            b = carry
        return a if a <= 0x7fffffff else ~(a ^ x)

Explain

此题解使用位操作来实现两个数的加法,避免了使用四则运算符。首先,将输入的整数 a 和 b 限制在 32 位整数范围内。在主循环中,使用位与操作 `&` 和位左移操作 `<<` 来计算两数相加的进位,使用位异或操作 `^` 来计算两数相加时的无进位和。循环继续,直到没有进位(即 b 为 0)。最后,如果计算结果 a 超过 32 位整数的正数最大值,通过位操作将其转换为正常的 Python 整数表示。

时间复杂度: O(1)

空间复杂度: O(1)

class Solution:
    def add(self, a: int, b: int) -> int:
        x = 0xffffffff  # 限制 a 和 b 在 32 位整数范围内
        a &= x
        b &= x
        while b != 0:  # 循环直到没有进位
            carry = (a & b) << 1 & x  # 计算进位:同为1的位才进位,并左移1位
            total = a ^ b  # 计算无进位的和:不同位为1
            a = total
            b = carry
        return a if a <= 0x7fffffff else ~(a ^ x)  # 如果结果是负数,转换为正常的整数表示

Explore

在Python中,整数类型是无限精度的,而在大多数编程语言和计算机硬件中,整数通常有固定的大小和范围(如32位整数)。限制`a`和`b`在32位整数范围内是为了模拟这种环境,确保算法在其他语言或硬件上具有相同的行为和性能。此外,这种限制有助于处理32位整数溢出的情况,使算法能够正确地处理超出32位表示范围的数值。

在位操作加法中,计算进位时使用`carry = (a & b) << 1`得到进位值。将此值与`0xffffffff`进行与操作是为了确保进位结果仍然是一个有效的32位整数。这样可以防止进位计算结果超出32位整数的范围,确保每个步骤的计算都严格限制在32位内。这是处理Python中整数无限精度特性的一个技巧,确保算法的行为与实际32位整数环境一致。

在这种位操作实现的加法算法中,`b`变量用于存储当前的进位值。当`a`和`b`的对应位都为1时,将会产生进位。算法通过循环将当前的进位值`carry`赋给`b`,然后计算`a`和新的`b`(即进位)的无进位和和新的进位。当`b`变为0时,意味着没有更多的进位需要处理,即两个数的所有位上加法及进位处理完毕,此时`a`包含了最终的加法结果。因此,`b`为0可以作为循环终止的条件,表示所有进位都已经被归并到最终结果中。

算法通过限制`a`和`b`在32位整数范围内,并且在计算过程中对进位进行适当处理,确保了即使输入值接近32位整数的边界也能得到正确的结果。当最终结果超过32位整数正数的最大值时,算法还包含了一个转换步骤,将超出范围的结果转换成正确的32位整数表示。因此,即便`dataA`和`dataB`的值非常大,只要遵循32位限制,该算法仍能够准确地计算出正确的结果。