- 关于按位操作符 & | 和 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
- 关于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)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- 关于 剑指 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)做一个二进制的格式化,然后全局取反(~)加上符号位,最后就能输出真实值。
- 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取反符号对首位的符号位不生效