按位运算符 & 在 Python
Bitwise operator & in Python
最近,我正在解决 Hackerrank 的一个非常基本的条件问题。
问题是:
If n is odd, print Weird
If n is even and in the inclusive range of 2 to 5 print Not Weird
If n is even and in the inclusive range of 6 to 20 print Weird
If n is even and greater than 20, print Not Weird
所以我写了下面的代码
if(n % 2 == 0 & n >=6 & n <= 20 ):
print("Weird")
elif(n % 2 == 0 & n <= 2 & n >= 5):
print("Not Weird")
elif( n % 2 != 0):
print("Weird")
else:
print("Not Weird")
一开始没用。我发现我必须使用 "and" 而不是“&”。
但是,我不相信为什么会这样..
对于 n = 12,第一个 if 条件的所有 3 个条件都为真。所以 true & true & true 应该也是真的吧?
this photo shows the code snippet with some print messages
我很想知道这种行为背后的原因,请指导! (可能是非常小的事情,但请不要介意:))
for n = 12, all 3 conditions of the first if condition are true.
>>> n = 12
>>> n % 2 == 0 & n >= 6 & n <= 20
False
第二个条件为假(条件不是你想的那样,因为按位运算符与其他数字运算符相似[+
、-
、%
, 等],因为它们比比较运算符具有更高的优先级)。
让我们稍微分解一下:
>>> n % 2
0
>>> 0 & n
0
>>> 6 & n
4
>>> 0 == 0 >= 4 <= 20
False
由于 0 & n >= 6 & n
条件,表达式为假。 0 不大于 4!
从 grammar 中可能不是很明显,但是二进制算术运算比二进制按位运算绑定得更紧密。所以你的比较和
一样
>>> if(n % 2 == (0 & n) >= (6 & n) <= 20 ):
... print("Weird")
...
>>>
你的"true & true &true"案例是
>>> if((n % 2 == 0) & (n >=6) & (n <= 20) ):
... print('Weird')
...
Weird
但这只有效,因为 python True
和 False
评估为 1
和 0
。由于这种底层表示,按位运算才有效。
每次有这样的疑惑,可以使用dis
模块,在你的情况下我做了一个lambda函数来评估过程:
func = lambda x: x % 2 == 0 & x >= 6 & x <= 20
这为我们提供了以下反汇编代码:
0 LOAD_FAST 0 (x)
2 LOAD_CONST 1 (2)
4 BINARY_MODULO
6 LOAD_CONST 2 (0)
8 LOAD_FAST 0 (x)
10 BINARY_AND
12 DUP_TOP
14 ROT_THREE
16 COMPARE_OP 2 (==)
18 JUMP_IF_FALSE_OR_POP 40
20 LOAD_CONST 3 (6)
22 LOAD_FAST 0 (x)
24 BINARY_AND
26 DUP_TOP
28 ROT_THREE
30 COMPARE_OP 5 (>=)
32 JUMP_IF_FALSE_OR_POP 40
34 LOAD_CONST 4 (20)
36 COMPARE_OP 1 (<=)
38 RETURN_VALUE
>> 40 ROT_TWO
42 POP_TOP
44 RETURN_VALUE
解释只是:
- 获取变量
x
值
- 获取常量
2
值
- 得到
modulo
比较2
和x
,当你使用12
作为参数值时,答案是0
。
- 获取常量
0
值
- 获取变量
x
值
- 得到
0
和x
之间的二进制and
比较,自然地,任何值(例如:b'1100'
)和b'0000'
之间的位操作将return 0
.
- 接下来,将值存储在 TOP 中并与
==
运算符进行比较。这意味着此时其他答案说 (x % 2) == (0 & x)
,x
是 12
,翻译后的操作是 0 == 0
(真)。
- 使用
==
结果检查是否为 False(在这种情况下,跳转到字节码的第 40
行)否则,从 TOS(堆栈顶部)中删除结果 (POP)
- 获取常量
6
值
- 获取变量
x
值
- 另一个
and
比较,这次是6
(b'0110'
)和12
(x
=b'1100'
)之间的结果4
(b'0100'
)
- 最后的结果存储在 TOP 中,并与
>=
运算符与最后存储的值进行比较(0 >= 4
如其他答案所述)。
- 来自
0 >= 4
的响应然后在下一条指令中进行评估,False
导致代码直接跳到指令 40
(Return False),甚至没有测试最后一个案例。
当然,这是 python 如何工作的字节码解释,简短的回答是 0 & n >= 6 & n
的事情,考虑到这一点,我们可以假设每个不同于 0 的数字,将return 此评估为假,因为 b'0110'
之间的按位运算将始终大于 0。
TL;DR
按位运算符在布尔运算符之前计算。
参考资料
最近,我正在解决 Hackerrank 的一个非常基本的条件问题。
问题是:
If n is odd, print Weird
If n is even and in the inclusive range of 2 to 5 print Not Weird
If n is even and in the inclusive range of 6 to 20 print Weird
If n is even and greater than 20, print Not Weird
所以我写了下面的代码
if(n % 2 == 0 & n >=6 & n <= 20 ):
print("Weird")
elif(n % 2 == 0 & n <= 2 & n >= 5):
print("Not Weird")
elif( n % 2 != 0):
print("Weird")
else:
print("Not Weird")
一开始没用。我发现我必须使用 "and" 而不是“&”。
但是,我不相信为什么会这样..
对于 n = 12,第一个 if 条件的所有 3 个条件都为真。所以 true & true & true 应该也是真的吧?
this photo shows the code snippet with some print messages
我很想知道这种行为背后的原因,请指导! (可能是非常小的事情,但请不要介意:))
for n = 12, all 3 conditions of the first if condition are true.
>>> n = 12
>>> n % 2 == 0 & n >= 6 & n <= 20
False
第二个条件为假(条件不是你想的那样,因为按位运算符与其他数字运算符相似[+
、-
、%
, 等],因为它们比比较运算符具有更高的优先级)。
让我们稍微分解一下:
>>> n % 2
0
>>> 0 & n
0
>>> 6 & n
4
>>> 0 == 0 >= 4 <= 20
False
由于 0 & n >= 6 & n
条件,表达式为假。 0 不大于 4!
从 grammar 中可能不是很明显,但是二进制算术运算比二进制按位运算绑定得更紧密。所以你的比较和
一样>>> if(n % 2 == (0 & n) >= (6 & n) <= 20 ):
... print("Weird")
...
>>>
你的"true & true &true"案例是
>>> if((n % 2 == 0) & (n >=6) & (n <= 20) ):
... print('Weird')
...
Weird
但这只有效,因为 python True
和 False
评估为 1
和 0
。由于这种底层表示,按位运算才有效。
每次有这样的疑惑,可以使用dis
模块,在你的情况下我做了一个lambda函数来评估过程:
func = lambda x: x % 2 == 0 & x >= 6 & x <= 20
这为我们提供了以下反汇编代码:
0 LOAD_FAST 0 (x)
2 LOAD_CONST 1 (2)
4 BINARY_MODULO
6 LOAD_CONST 2 (0)
8 LOAD_FAST 0 (x)
10 BINARY_AND
12 DUP_TOP
14 ROT_THREE
16 COMPARE_OP 2 (==)
18 JUMP_IF_FALSE_OR_POP 40
20 LOAD_CONST 3 (6)
22 LOAD_FAST 0 (x)
24 BINARY_AND
26 DUP_TOP
28 ROT_THREE
30 COMPARE_OP 5 (>=)
32 JUMP_IF_FALSE_OR_POP 40
34 LOAD_CONST 4 (20)
36 COMPARE_OP 1 (<=)
38 RETURN_VALUE
>> 40 ROT_TWO
42 POP_TOP
44 RETURN_VALUE
解释只是:
- 获取变量
x
值 - 获取常量
2
值 - 得到
modulo
比较2
和x
,当你使用12
作为参数值时,答案是0
。 - 获取常量
0
值 - 获取变量
x
值 - 得到
0
和x
之间的二进制and
比较,自然地,任何值(例如:b'1100'
)和b'0000'
之间的位操作将return0
. - 接下来,将值存储在 TOP 中并与
==
运算符进行比较。这意味着此时其他答案说(x % 2) == (0 & x)
,x
是12
,翻译后的操作是0 == 0
(真)。 - 使用
==
结果检查是否为 False(在这种情况下,跳转到字节码的第40
行)否则,从 TOS(堆栈顶部)中删除结果 (POP) - 获取常量
6
值 - 获取变量
x
值 - 另一个
and
比较,这次是6
(b'0110'
)和12
(x
=b'1100'
)之间的结果4
(b'0100'
) - 最后的结果存储在 TOP 中,并与
>=
运算符与最后存储的值进行比较(0 >= 4
如其他答案所述)。 - 来自
0 >= 4
的响应然后在下一条指令中进行评估,False
导致代码直接跳到指令40
(Return False),甚至没有测试最后一个案例。
当然,这是 python 如何工作的字节码解释,简短的回答是 0 & n >= 6 & n
的事情,考虑到这一点,我们可以假设每个不同于 0 的数字,将return 此评估为假,因为 b'0110'
之间的按位运算将始终大于 0。
TL;DR
按位运算符在布尔运算符之前计算。