Can you please give me a proper link to read or explain how does this code in Python3 work?
print("NO" if (n := int(input())) & (n - 1) else "YES")
As far as I understood it checks whether given integer n is equal to some power of 2, but how the hell does it check it.
CodePudding user response:
Evaluating the code from the outside in, the print()
call will print out either "NO"
or "YES"
based on the conditional expression (also called ternary operator) value1 if condition else value2
.
The condition in this case is (n := int(input())) & (n-1)
. The expression to the left of &
is called an assignment expression and is also called the walrus because of how :=
looks. It assigns the result of int(input())
to n
and also uses that value as part of the condition. This way, you can avoid initializing n
on a separate line (or calling a method again, if it wasn't user input) before re-using it in the right hand side of the condition as n-1
.
&
is the bitwise AND operation. To see why (n & (n-1)) == 0
is a valid condition for checking if n
is a power of 2, take a look at this question: Query about working out whether number is a power of 2 .
Your conditional expression omits == 0
because 0
will be treated as False
, and puts the desired output - "YES"
, for n
being a power of 2 - in the else
clause.
CodePudding user response:
It has to do with the way an integer is stored in binary.
&
is a bit-operator which is an AND
gate for the bits left and right of it. And works like this for two bits:
1 & 1 => 1
1 & 0 => 0
0 & 1 => 0
0 & 0 => 0
Due to the binary representation every power of 2 is represented with a 1
at a position i
and all zeroes on all positions < i
. Because of that and the way AND
works we only get a 1
bit if we have 1
at both positions left and right. So for every power of two we have a single 1
and the rest all zeroes and for every value that is not a power of two will use <= i-1
bits, at least one of which is different from zero.
The result of the operation n & (n - 1)
, if we have a power of two power_of_two & power_of_two - 1
, will always return 0
which is a falsy
value in Python so the else
branch will be triggered. For every value that is not a power of two not_power_of_two & not_power_of_two - 1
will return something != 0
which is a truthy
value in Python hence "NO"
is returned.
Probably this example is easier to understand that all the text above:
Input | Binary repr. input | Binary repr. input -1 | Result AND (&) binary | Result AND decimal | Python truthy/ falsy |
---|---|---|---|---|---|
0 | 0b0000 | 0b1111 | 0b0000 | 0 | falsy |
1 | 0b0001 | 0b0000 | 0b0000 | 0 | falsy |
2 | 0b0010 | 0b0001 | 0b0000 | 0 | falsy |
3 | 0b0011 | 0b0010 | 0b0010 | 2 | truthy |
4 | 0b0100 | 0b0011 | 0b0000 | 0 | falsy |