问题描述:
Recently I was solving one of the very basic problems on conditionals from Hackerrank.
The problem was:
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
So i wrote the following code
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")
It didn’t work at first. I figured out that i had to use “and” instead of “&”.
But, I am not convinced why did this happen..
for n = 12, all 3 conditions of the first if condition are true. so true & true & true should also be true, right?
this photo shows the code snippet with some print messages
I am very intrigued to know the reason behind this behaviour, please guide! (may be something very minor but please don’t mind :) )
解决方案 1[最佳方案][1]
Every time you have this kind of doubts, you can use the dis
module, in your case I make a lambda function to evaluate the process:
func = lambda x: x % 2 == 0 & x >= 6 & x <= 20
this gives us the follow disassmbled code:
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
explained is just:
- Get var
x
value - Get const
2
value - Get
modulo
comparison between2
andx
, the answer is0
when you use12
as the param value. - Get const
0
value - Get var
x
value - Get Binary
and
comparison between0
andx
, naturally, a bitwise operation between any value (eg:b'1100'
) andb'0000'
will return0
. - Next, values are stored in TOP and compared with
==
operator. This means as other answers said(x % 2) == (0 & x)
at this time, withx
being12
, the translated operation is0 == 0
(True). - With the
==
result check if is False (in that case, jump to row40
of bytecode) else, remove the result (POP) from TOS (Top of stack) - Get const
6
value - Get var
x
value - Another
and
comparison, this time between6
(b'0110'
) and12
(x
=b'1100'
) with a result of4
(b'0100'
) - The last result is stored in TOP and compared with
>=
operator with the last stored value (0 >= 4
as said in other answers). - Response from
0 >= 4
is then, evaluated in the next instruction,False
causes than the code skip directly to the instruction40
(Return False) without even test the last case.
Of course, this is the bytecode explanation of how python works, the short answer is the 0 & n >= 6 & n
thing, with this in mind, we can assume than every number different from 0, will return False to this evaluation, because a bitwise operation between b'0110'
will always be greater than 0.
TL;DR
Bitwise operators are evaluated before Boolean operators.
References
https://docs.python.org/3.8/library/dis.html Dis module reference.
解决方案 2:[2]
for n = 12, all 3 conditions of the first if condition are true.
>>> n = 12
>>> n % 2 == 0 & n >= 6 & n <= 20
False
The second condition is false (and the conditions aren’t what you think they are, because bitwise operators are similar to other numeric operators [+
, -
, %
, etc] in that they have higher precedence than comparison operators).
Let’s break this down a little:
>>> n % 2
0
>>> 0 & n
0
>>> 6 & n
4
>>> 0 == 0 >= 4 <= 20
False
The expression is false because of the 0 & n >= 6 & n
condition. 0 isn’t greater than 4!
解决方案 3:[3]
It may not be immediately obvious from the grammar, but binary arithmetic operations bind tighter than binary bitwise operations. So your comparison is the same as
>>> if(n % 2 == (0 & n) >= (6 & n) <= 20 ):
... print("Weird")
...
>>>
Your “true & true &true” case is
>>> if((n % 2 == 0) & (n >=6) & (n <= 20) ):
... print('Weird')
...
Weird
But that only works because python True
and False
evaluate to 1
and 0
. A bitwise operation only works because of this underlying representation.
参考链接:
Copyright Notice: This article follows StackOverflow’s copyright notice requirements and is licensed under CC BY-SA 3.0.
Article Source: StackOverflow
[1] Erick IO
[2] Samwise
[3] tdelaney