Подтвердить что ты не робот

Странный оператор if

Я нашел это странное if -statement в некотором elses-коде:

if variable & 1 == 0:

Я не понимаю. Он должен иметь два ==, правильно?

Может кто-нибудь объяснить это?

4b9b3361

Ответ 1

Условное выражение побитового оператора:

>>> 1 & 1
1
>>> 0 & 1
0
>>> a = 1
>>> a & 1 == 0
False
>>> b = 0
>>> b & 1 == 0
True

Как отмечают многие комментарии, для целых чисел это условие равно True для evens и False для коэффициентов. Наиболее распространенный способ написать это: if variable % 2 == 0: или if not variable % 2:

Используя timeit, мы видим, что в производительности нет большой разницы.

n & 1 ("== 0" and "not")

>>> timeit.Timer("bitwiseIsEven(1)", "def bitwiseIsEven(n): return n & 1 == 0").repeat(4, 10**6)
[0.2037370204925537, 0.20333600044250488, 0.2028651237487793, 0.20192503929138184]

>>> timeit.Timer("bitwiseIsEven(1)", "def bitwiseIsEven(n): return not n & 1").repeat(4, 10**6)
[0.18392395973205566, 0.18273091316223145, 0.1830739974975586, 0.18445897102355957]

n % 2 ("== 0" and "not")

>>> timeit.Timer("modIsEven(1)", "def modIsEven(n): return n % 2 == 0").repeat(4, 10**6)
[0.22193098068237305, 0.22170782089233398, 0.21924591064453125, 0.21947598457336426]

>>> timeit.Timer("modIsEven(1)", "def modIsEven(n): return not n % 2").repeat(4, 10**6)
[0.20426011085510254, 0.2046220302581787, 0.2040550708770752, 0.2044820785522461]

Перегруженные операторы:

Операторы % и & перегружены.

Побитовое и оператор перегружен для set. s.intersection(t) эквивалентен s & t и возвращает "новый набор с элементами, общими для s и t".

>>> {1} & {1}
set([1])

Это не влияет на наше условное выражение:

>>> def bitwiseIsEven(n):
...   return n & 1 == 0

>>> bitwiseIsEven('1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in bitwiseIsEven
TypeError: unsupported operand type(s) for &: 'str' and 'int'
>>> bitwiseIsEven({1})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in bitwiseIsEven
TypeError: unsupported operand type(s) for &: 'set' and 'int'

Оператор modulo также бросает TypeError: unsupported operand type(s) для большинства не-ints.

>>> def modIsEven(n):
...   return n % 2 == 0

>>> modIsEven({1})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in modIsEven
TypeError: unsupported operand type(s) for %: 'set' and 'int'

Он перегружен как оператор интерполяции строк для старого %-formatting. Он выбрасывает TypeError: not all arguments converted during string formatting, если для сравнения используется строка.

>>> modIsEven('1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in modIsEven
TypeError: not all arguments converted during string formatting

Это не будет выдаваться, если строка содержит действительный спецификатор преобразования.

>>> modIsEven('%d')
False 

Ответ 2

Этот код просто проверяет, является ли младший бит variable равным 0. На основе приоритета оператора это:

if (variable & 1) == 0:

Сначала И младший бит с одним (выведите только самый младший бит), затем проверьте, равно ли оно 0.

Ответ 3

И это побитовый оператор. Он возвращает целое число с 1 битом для каждого бита его двух операндов, которые равны 1 и 0 во всех других местах. Например:

a = 10 # 0b1010
b = 6  # 0b0110
a & b  # 0b0010

Теперь, если у вас есть variable & 1, вы сравниваете variable с 0b1, который будет возвращать только 1, если последняя цифра в двоичном представлении равна 1, иначе 0.

Ответ 4

Ваша единственная проблема - это, скорее всего, оператор &. Это побитовое и, которое берет двоичный формат двух операндов и выполняет "логику" и "каждую пару бит".

В вашем примере рассмотрим следующее:

variable = 2  #0b0010
if variable & 1 == 0:
    print "condition satisfied" # satisfied, 0b0010 & 0b0001 = 0

variable = 5  #0b0101
if variable & 1 == 0:
    print "condition satisfied" # not satisfied, 0b0101 & 0b0001 = 1

Примечание:

variable = 6  #0b0110
if variable & 2 == 0:
    print "condition satisfied" # not satisfied, 0b0110 & 0b0010 = 2 (0b0010)