Python:关于按位操作的说明(leetcode 剑指 Offer 65. 不用加减乘除做加法)

本文探讨了Python中按位操作符(&、|)与and、or的区别,以及它们在数值变量二进制表示中的应用。通过示例解释了如何使用按位操作实现加法,并详细解析了代码过程。同时,文章还涉及了Python中负数的二进制表示和按位取反操作符~的理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 关于按位操作符 & | 和 and or 的区别
    对于数值类变量:
    &:对符号两侧变量的每一位执行 与 操作
    |:对符号两侧变量的每一位执行 或 操作
    and:含0返回0,均为非0返回最后一个值
    or:至少有1个非0时,返回第一个非0
# 1&2,2在二进制里面是10,1在二进制中是01,那么01与运算10得到是0 
# 1:01  2:10  3:11
1 & 2         # 输出为 0, 
1 | 2          # 输出为3

 # 判断变量是否为0, 是0则为False,非0判断为True,
 # and中含0,返回0; 均为非0时,返回后一个值, 
2 and 0   # 返回0
2 and 1   # 返回1
1 and 2   # 返回2

# or中, 至少有一个非0时,返回第一个非0,
2 or 0   # 返回2
2 or 1   # 返回2
0 or 1   # 返回1 
  1. 关于Python中数值变量二进制显示的机制
print(hex(1)) # = 0x1 补码
print(hex(-1)) # = -0x1 负号 + 原码 ( Python 特色,Java 会直接输出补码)

print(hex(1 & 0xffffffff)) # = 0x1 正数补码
print(hex(-1 & 0xffffffff)) # = 0xffffffff 负数补码

print(-1 & 0xffffffff) # = 4294967295 ( Python 将其认为正数)

作者:jyd
链接:https://leetcode-cn.com/problems/bu-yong-jia-jian-cheng-chu-zuo-jia-fa-lcof/solution/mian-shi-ti-65-bu-yong-jia-jian-cheng-chu-zuo-ji-7/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  1. 关于 剑指 Offer 65. 不用加减乘除做加法 的理解
    题目如下:写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。

代码如下:

class Solution:
    def add(self, a: int, b: int) -> int:
        x = 0xffffffff
        a, b = a & x, b & x
        print("{:032b}".format(a), "{:032b}".format(b))
        while b != 0:
            a, b = (a ^ b), (a & b) << 1 & x
            print("{:032b}".format(a), "{:032b}".format(b))
        return a if a <= 0x7fffffff else ~(a ^ x)

首先, x的作用实际上是规定了a/b变量的二进制化后的范围,8个f实际上就是规定长度为32位二进制数。我尝试把第7行的 & x 给删掉,发现结果错误了,其原因就是变量b最后运行时,出现了溢出,长度由32变到了33,在计算a = -1, b = 2时结果出错。

其次, 变量a, b 初始值为传入的待计算的值。运行过程中,a保存的是非进位和,b保存的是每一次进位的结果。由于非进位和 加上 进位结果 后( a & b 操作)会继续产生进位,因此循环终止条件是b为0,即最终没产生新的进位后结束循环。

最后, 正数的补码是正数本身,负数的补码是原码取反+1,第一位为符号位。因此,对于第一位是0开头(<= 0x7fffffff)的数,是正数,直接返回即可。由于此时是补码表示,直接输出负数的补码,python默认输出的是不带符号位的二进制数,这样就导致了错误。因此,需要将负数的补码转换为真正的负数,操作为两次取反:先按位取反(^ 0xf)做一个二进制的格式化,然后全局取反(~)加上符号位,最后就能输出真实值。

  1. Python中按位操作 和 ~ 操作符的理解如下:
# ^ 0xf 和 ~
# ^ 0xf 会忽略其符号为 对所有位都生效
# ~ 对符号为不生效,具体来说 如果首位是0 取反后变为1  如果首位是1 python认为其为符号位, 不会将首位的1变为0
x = 0xf
g = 3 & x
g_s = "{:04b}".format(g)
print(g_s)  # 输出 0011

h = ~g
print(h)   # 输出-4
h_s = "{:04b}".format(h)
print(h_s)  # 输出 -100 实际上是1100

i = g ^ x
print(i)   # 输出12
i_s = "{:04b}".format(i)
print(i_s)  # 输出1100

j = h & x  # h:1100
print(j)  # 输出12  经过按位操作符&(^也是一样)处理后 默认不带符号位
j_s = "{:04b}".format(j)
print(j_s)  # 输出1100

k = ~j
print(k)  # 输出 - 13  取反后k变为:1 0011 第一个1表示符号位 此时这个码是补码 对应的值应该为 -13
k_s = "{:04b}".format(k)
print(k_s)  # 输出 -1101 python取反符号对首位的符号位不生效

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值