Побитовое исключающее или: Побитовые операторы
Содержание
PHP побитовые операторы
Побитовые операторы выполняют низкоуровневые манипуляции с битами в двоичных представлениях чисел. Эти операторы редко используются в программировании на PHP, поэтому если вы не знакомы с двоичным представлением целых чисел, то можете пропустить этот раздел. Побитовые операторы выполняют поразрядные операции булевой алгебры над отдельными битами операндов.
В наличии PHP есть 6 побитовых операторов:
Побитовое И (&)
Оператор &
выполняет операцию логическое И над каждым битом своих операндов. Бит результата устанавливается, если соответствующий бит установлен в обоих операндах.
Пример работы оператора «Побитовое И»:
Тоже самое только на примере PHP:
<?php $x = 3; // ...0011 $y = 5; // ...0101 echo $x & $y; // ...0001 (1) ?>
Побитовое ИЛИ (|)
Оператор |
выполняет операцию логическое ИЛИ над каждым битом своих операндов. $y; // …0110 (6)
?>
Побитовое НЕ (~)
Оператор ~
(побитовое НЕ) представляет собой унарный оператор, указываемый перед своим единственным операндом. Он выполняет инверсию всех битов операнда. Из-за способа представления целых со знаком в PHP применение оператора ~
к значению эквивалентно изменению его знака и вычитанию 1.
Пример работы оператора «Побитовое НЕ»:
Тоже самое только на примере PHP:
<?php $y = 5; // ...0101 echo ~$y; // ...1010 (-6) ?>
Осталось рассмотреть два оператора — сдвиг влево и сдвиг вправо. Эти операторы можно использовать для быстрого умножения и деления (каждая позиция подразумевает «умножение/деление на 2»).
Сдвиг влево (<<)
Оператор <<
сдвигает все биты в первом операнде влево на количество позиций, указанное во втором операнде, который должен быть целым числом. Сдвиг значения влево на одну позицию эквивалентен умножению на 2, на две позиции — умножению на 4 и т.д.
Пример работы оператора «Сдвиг влево»:
<?php $y = 5; // 000000101 // тоже самое что и 5 * 4 echo $y << 2; // 000010100 (20) ?>
Сдвиг вправо (>>)
Оператор >>
сдвигает все биты в первом операнде вправо на количество позиций, указанное во втором операнде, который должен быть целым числом. Сдвиг значения вправо на одну позицию эквивалентен делению на 2, на две позиции — делению на 4 и т.д.
Пример работы оператора «Сдвиг вправо»:
<?php $y = 20; // 000010100 // тоже самое что и 20 / 4 echo $y >> 2; // 000000101 (5) ?>
Помимо описанных операторов, в PHP также предусмотрены и сокращенные формы записи побитовых операторов.
Оператор | Описание | Пример | Сокращенная форма записи |
---|---|---|---|
&= | Присваивает левому операнду результат работы Побитового И | $x = $x & $y | $x &= $y |
|= | Присваивает левому операнду результат работы Побитового ИЛИ | $x = $x | $y | $x |= $y |
^= | Присваивает левому операнду результат работы Исключающего ИЛИ | $x = $x ^ $y | $x ^= $y |
>>= | Присваивает левому операнду результат работы оператора Сдвига вправо | $x = $x >> 6 | $x >>= 6 |
<<= | Присваивает левому операнду результат работы оператора Сдвига влево | $x = $x << 6 | $x <<= 6 |
С этой темой смотрят:
Битовые операции.)
Битовые операции с переменными проводятся на битовом уровне. Данные операции позволяют решать многие проблемы программирования. Представленный материал поможет долстаточно полно разобраться с битовыми операциями.
Описание и синтаксис
Побитовое И (&)
Побитовое И в языке C это одиночный амперсанд (&), используется между двух выражений. Побитовое И оперирует с каждым битом переменных по отдельности, руководствуся правилом — если оба бита перменных одного разряда равны 1, то результатом также будет 1 в данном разряде. В любом другом случае в результате получится ноль.
0 0 1 1 операнд1
0 1 0 1 операнд2
———-
0 0 0 1 (операнд & операнд2) — возвращаемый результат
В Arduino, тип данных int занимает 16-бит, поэтому использование & между двумя переменными типа int вызывает одновременное сравнение 16 бит. Рассмотрим этот код:
int a = 92; // в битовом виде: 0000000001011100
int b = 101; // в битовом виде: 0000000001100101
int c = a & b; // результат: 0000000001000100, или 68 в десятичной системе счисления. операнд2) — возвращаемый результат
По другому алгоритм можно описать так — если биты различны, возвращается 1 и возвращается 0 если они одинаковы.
побитовый сдвиг влево (<<), побитовый сдвиг вправо(>>)
Описание:
Данные два оператора сдвигают влево или вправо значения битов переменной слева на количество, указанное в переменной справа.
Синтаксис:
переменная << число бит
переменная >> число бит
Параметры:
переменная — (byte, int, long) число <= 32
Пример:
int a = 5; // в битовом виде: 0000000000000101
int b = a << 3; // в битовом виде: 0000000000101000, или 40 в десятичной системе счисления
int c = b >> 3; // в битовом виде: 0000000000000101, или 5 с чего мы и начали
Вы можете легко потерять биты, слишком много сдвинув их влево:
int a = 5; // binary: 0000000000000101
int b = a << 14; // binary: 0100000000000000 — старшая 1 в 101 была потеряна
Самым простым способом применения операторов сдвига является нахождение степени числа 2.
1 << 0 == 1
1 << 1 == 2
1 << 2 == 4
1 << 3 == 8
…
1 << 8 == 256
1 << 9 == 512
1 << 10 == 1024
…
Если вы сдвигаете биты отрацительной переменной, то старший бит при сдвиге вправо копируется:
int x = -16; // binary: 1111111111110000
int y = x >> 3; // binary: 1111111111111110
Данный пример выдает не то что нам нужно. Чтобы старший бит не копировался, необходимо указать это:
int x = -16; // binary: 1111111111110000
int y = (unsigned int)x >> 3; // binary: 0001111111111110
Если вы осторожны в своих действиях, то можете применять сдвиг вправо для деления переменных на степень двойки.
Например:
int x = 1000;
int y = x >> 3; // целочисленное деление 1000 на 8, возвратит y = 125.
Советы программисту:
данные операции выполняются с высоким быстродействием, так как работа идет с целочисленными переменными. x могут быть заменены на 0
(самообратное свойство). И любой 0
может быть удален (потому что это личность).
Повторите как можно дольше. Любое число, которое появляется четное число раз, имеет целое число пар, поэтому все они становятся 0 и исчезают.
В конце концов у вас остается только один элемент, который появляется нечетное количество раз. Каждый раз, когда он появляется дважды, эти двое исчезают. В конце концов вы остались с одним случаем.
[Обновление]
Обратите внимание, что это доказательство требует только определенных предположений об операции. В частности, предположим, что множество S с оператором .
имеет следующие свойства:
Ассоциативность: x . (y . z) = (x . y) . z
для любого x
, y
и z
в S.
Идентичность: существует единственный элемент e
, такой что e . x = x . e = x
для всех x
в S.
Закрытие: Для любых x
и y
в S x . y
также находится в S.
Самообратный: для любого x
в S, x . x = e
Оказывается, нам не нужно предполагать коммутативность; мы можем доказать это:
(x . y) . (x . y) = e (by self-inverse)
x . (y . x) . y = e (by associativity)
x . x . (y . x) . y . y = x . e . y (multiply both sides by x on the left and y on the right)
y . x = x . y (because x . x = y . y = e and the e's go away)
Теперь я сказал, что «вам не нужно ничего знать об отдельных битах». Я думал, что любой группе, удовлетворяющей этим свойствам, будет достаточно, и что такая группа не обязательно должна быть изоморфна целым числам в XOR.
Но @Steve Jessup доказал, что я не прав в комментариях. Если вы определяете скалярное умножение на {0,1} как:
0 * x = 0
1 * x = x
… тогда эта структура удовлетворяет всем аксиомам векторного пространства над целыми числами mod 2.
Таким образом, любая такая структура изоморфна набору векторов битов в компонентном XOR.
Побитовые операторы в PHP
Что такое побитовые операторы?
Побитовые операторы — арифметическая операция, которая отвечает за побитовый сдвиг в PHP.
Биты, сдвинутые за границы числа, отбрасываются. Сдвиг влево дополняет число нулями справа, сдвигая в то же время знаковый бит числа влево, что означает что знак операнда не сохраняется. Сдвиг вправо сохраняет копию сдвинутого знакового бита слева, что означает что знак операнда сохраняется.
Для чего нужны побитовые операторы?
Побитовые операторы в PHP позволяют считывать и устанавливать конкретные биты целых чисел.
Синтаксис побитовых операторов
Синтаксис всех побитовых операторов представлен в таблице ниже.
Пример | Название | Результат | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$a & $b | И | Устанавливаются только те биты, которые установлены и в $a, и в $b. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$a | $b | Или | Устанавливаются те биты, которые установлены в $a или в $b. являются строками, то операция будет выполнена над ASCII значениями символов, составляющих эти строки, и результатом будет строка. В других случаях, оба операнда будут приведены к целому и результатом будет тоже целое число. Если операнд для оператора ~ является строкой, то операция будет произведена над ASCII значением символов, составляющих эту строку, и результатом будет строка. Иначе, и операнд и результат будут оперироваться как целые числа. Метки: PHP, Операторы. Битовые операции☰ Во многих языках программирования допустимы логические операции над битами целых чисел. В отличие от обычных логических операций, результатом выполнения которых является логический тип данных, битовые логические операции просто изменяют целое число согласно определенным правилам. Точнее битовые операции изменяют отдельные биты двоичного представления числа, в результате чего изменяется его десятичное значение. Например, в языке программирования Паскаль обычные логические операции и логические операции над битами обозначают с помощью одних и тех же ключевых слов: Как понять побитовые операции1. Переведем пару произвольных целых чисел до 256 (один байт) в двоичное представление. 6710 = 0100 00112 11410 = 0111 00102 2. Теперь расположим биты второго числа под соответствующими битами первого и выполним обычные логические операции к цифрам, стоящим в одинаковых разрядах первого и второго числа. Например, если в последнем (младшем) разряде одного числа стоит 1, а другого числа — 0, то логическая операция 3. Переведем результат в десятичную систему счисления. 01000010 = 26 + 21 = 64 + 2 = 66 01110011 = 26 + 25 + 24 + 21 + 20 = 64 + 32 + 16 + 2 + 1 = 115 00110001 = 25 + 24 + 20 = 32 + 16 + 1 = 49 10111100 = 27 + 25 + 24 + 23 + 22 = 128 + 32 + 16 + 8 + 4 = 188 4. Итак, в результате побитовых логических операций получилось следующее: 67 and 114 = 66 67 or 114 = 115 67 xor 114 = 49 not 67 = 188 Вот еще один пример выполнения логических операций над битами. Проверьте его правильность самостоятельно. 5 and 6 = 4 5 or 6 = 7 5 xor 6 = 3 not 5 = 250 Зачем нужны побитовые логические операцииГлядя на результат побитовых операций, не сразу можно уловить закономерности в их результате. Поэтому непонятно, зачем нужны такие операции. Однако, они находят свое применение. В байтах не всегда хранятся числа. Байт или ячейка памяти может хранить набор флагов (установлен — сброшен), представляющих собой информацию о состоянии чего-либо. С помощью битовых логических операций можно проверить, какие биты в байте установлены в единицу, можно обнулить биты или, наоборот, установить в единицу. Также существует возможность сменить значения битов на противоположные. Проверка битовПроверка битов осуществляется с помощью битовой логической операции Представим, что имеется байт памяти с неизвестным нам содержимым. Известно, что логическая операция Другими словами, Обнуление битовЧтобы обнулить какой-либо бит числа, нужно его логически умножить на 0. Обратим внимание на следующее: 1111 1110 = 254 = 255 - 1 = 255 - 20 1111 1101 = 253 = 255 - 2 = 255 - 21 1111 1011 = 251 = 255 - 4 = 255 - 22 1111 0111 = 247 = 255 - 8 = 255 - 23 1110 1111 = 239 = 255 - 16 = 255 - 24 1101 1111 = 223 = 255 - 32 = 255 - 25 1011 1111 = 191 = 255 - 64 = 255 - 26 0111 1111 = 127 = 255 - 128 = 255 - 27 Т.е. чтобы обнулить четвертый с конца бит числа Установка битов в единицуДля установки битов в единицу используется побитовая логическая операция Отметим также, что: 0000 0001 = 20 = 1 0000 0010 = 21 = 2 0000 0100 = 22 = 4 0000 1000 = 23 = 8 0001 0000 = 24 = 16 0010 0000 = 25 = 32 0100 0000 = 26 = 64 1000 0000 = 27 = 128 Поэтому, например, чтобы установить второй по старшинству бит числа Смена значений битовДля смены значений битов на противоположные используется битовая операция Операции побитового циклического сдвигаПомимо побитовых логических операций во многих языках программирования предусмотрены битовые операции циклического сдвига влево или вправо. Например, в языке программирования Паскаль эти операции обозначаются Первым операндом операций сдвига служит целое число, над которым выполняется операция. Во втором операнде указывается, на сколько позиций сдвигаются биты первого числа влево или вправо. Например, При сдвиге влево теряются старшие биты исходного числа, на их место становятся младшие. Освободившиеся младшие разряды заполняются нулями. При сдвиге вправо теряются младшие биты исходного числа, на их место становятся старшие. Освободившиеся старшие разряды заполняются нулями, если исходное число было положительным. Логические операции над числамиЛогические операции над числами 12.7 |
integer1 | 0 | 0 | 1 | 1 | |
integer2 | 0 | 1 | 0 | 1 | Имя операции |
logand | 0 | 0 | 0 | 1 | и |
logior | 0 | 1 | 1 | 1 | или |
logxor | 0 | 1 | 1 | 0 | исключающее или |
logeqv | 1 | 0 | 0 | 1 | эквивалентность (исключающее отрицающее или) |
lognand | 1 | 1 | 1 | 0 | не и |
lognor | 1 | 0 | 0 | 0 | не или |
logandc1 | 0 | 1 | 0 | 0 | не integer1 и integer2 |
logandc2 | 0 | 0 | 1 | 0 | integer1 и не integer2 |
logorc1 | 1 | 1 | 0 | 1 | не integer1 или integer2 |
logorc2 | 1 | 0 | 1 | 1 | integer1 или не integer2 |
Функция boole принимает операцию op и два целых числа, и возвращает
целое число полученное применением операции op к этим двум числам.
Точные значения шестнадцати констант зависят от реализации, но
они подходят для использования в качестве первого аргумента для
boole:
integer1 | 0 | 0 | 1 | 1 | |
integer2 | 0 | 1 | 0 | 1 | Выполняемая операция |
boole-clr | 0 | 0 | 0 | 0 | всегда 0 |
boole-set | 1 | 1 | 1 | 1 | всегда 1 |
boole-1 | 0 | 0 | 1 | 1 | integer1 |
boole-2 | 0 | 1 | 0 | 1 | integer2 |
boole-c1 | 1 | 1 | 0 | 0 | дополнение integer1 |
boole-c2 | 1 | 0 | 1 | 0 | дополнение integer2 |
boole-and | 0 | 0 | 0 | 1 | и |
boole-ior | 0 | 1 | 1 | 1 | или |
boole-xor | 0 | 1 | 1 | 0 | исключающее или |
boole-eqv | 1 | 0 | 0 | 1 | эквивалентность (исключительное отрицающее или) |
boole-nand | 1 | 1 | 1 | 0 | не и |
boole-nor | 1 | 0 | 0 | 0 | не или |
boole-andc1 | 0 | 1 | 0 | 0 | не integer1 и integer2 |
boole-andc2 | 0 | 0 | 1 | 0 | integer1 и не integer2 |
boole-orc1 | 1 | 1 | 0 | 1 | не integer1 или integer2 |
boole-orc2 | 1 | 0 | 1 | 1 | integer1 или не integer2 |
Таким образом boole может вычислять все шестнадцать логических
функций для двух аргументов. В целом,
(boole boole-and x y) ≡ (logand x y)
и далее по аналогии. boole полезна, когда необходимо параметризировать
процедуру так, что они может использовать одну из нескольких логических
операций.
Функция возвращает битовое логическое отрицание аргумента. Каждый
бит результата является дополнение соответствующего исходного бита
аргумента.
(logbitp j (lognot x)) ≡ (not (logbitp j x))
logtest является предикатом, который истинен, если любой бит
определённый как 1 в integer1 также является соответствующим битом 1 в
integer2.
(logtest x y) ≡ (not (zerop (logand x y)))
Предикат logbitp является истиной, если бит в позиции index в целом
числе integer (то есть, его вес 2index), является 1, иначе предикат ложен.
Например:
(logbitp 2 6) is true
(logbitp 0 6) is false
(logbitp k n) ≡ (ldb-test (byte 1 k) n)
index
должен быть неотрицательным целым числом.
Если count положительное число, данная функция арифметически
сдвигает число integer влево на количество бит count. Если count
отрицательное число, функция сдвигает число integer вправо. Знак
результата всегда такое же как и исходного числа integer.
Говоря математически, эта операция выполняет вычисления
floor(integer ⋅ 2count).
Логически, функция перемещает все биты числа integer влево, добавляя
нулевые биты в конец, или вправо отбрасывая биты в конце числа. (В этом
контексте вопрос о том, что сдвигается налево, не относится к делу. Целые
числа, рассматриваемые как строки битов, являются «полубесконечными», то
есть концептуально расширяются бесконечно влево FIXME.) Например:
(logbitp j (ash n k)) ≡ (and (>= j k) (logbitp (- j k) n))
Функция возвращает количество бит в числе integer. Если integer
положительное число, тогда подсчитаны будут биты 1. Если число integer
отрицательно, то в два раза дополненной (two’s-complement) бинарной
форме будут подсчитаны биты 0. FIXME Результатом всегда является
неотрицательное целое число. Например:
(logcount 13) ⇒ 3 ;Бинарное представление …0001101
(logcount -13) ⇒ 2 ;Бинарное представление …1110011
(logcount 30) ⇒ 4 ;Бинарное представление …0011110
(logcount -30) ⇒ 4 ;Бинарное представление …1100010
Следующее тождество всегда верно:
(logcount x) ≡ (logcount (- (+ x 1)))
≡ (logcount (lognot x))
Данная функция выполняет следующие вычисления
ceiling(log 2(if integer < 0 then −integer else integer + 1))
Эта функция полезна в двух случаях. Первое, если целое число integer не
отрицательно, тогда его значение может быть представлено в беззнаковой
бинарной форме в поле, ширина которого в битах не меньше чем
(integer-length integer). Второе, независимо от знака числа integer, его
значение может быть представлено как знаковая бинарная два раза
дополненная (two’s-complement) форма в поле, ширина которого в битах
не меньше чем (+ (integer-length integer) 1). х можно заменить на 0
(самообратных собственность). И любой 0
могут быть удалены (потому что он личность).
Как долго можно повторять. Любое число, которое появляется четное число раз имеет цельное количество пар, так что все они становятся 0 и исчезают.
В итоге у вас остается только один элемент, который появляется нечетное число раз. Каждый раз, когда он появляется дважды, эти двое исчезли. В конечном итоге вы остались с одним явлением.
[обновление]
Обратите внимание, что это доказательство требует только определенных предположениях об операции. В частности, предположим, что множество S с помощью оператора .
имеет следующие свойства:
Assocativity: х . (г . З) = (х . г) . Z
для любого Х
, Y
и Z
В С.
Личность: существует единичный элемент е такой, что е . х = х . Е = Хдля всех
X` в с.
Закрытие: для любого X
и y
В С `Х . г также В С.
Самообратных: для любого X
В С Х . х = е
Как выясняется, нам не нужно предполагать, коммутативность, мы можем это доказать:
Теперь, я сказал, что «вам не нужно ничего знать об отдельных битов и». Я думаю, что любая группа, удовлетворяющая этих свойств было бы достаточно, и что такие группы не обязательно должны быть изоморфны целых чисел по операции XOR.
Но @Стив Джессап доказала, что я ошибался в комментариях. Если определить скалярное умножение на {0,1} как:
…тогда эта структура отвечает всем аксиомы векторного пространства за мод целых чисел 2.
Таким образом, любая такая структура изоморфна набор векторов битов под покомпонентно гаммирования.
, ) сравнивает каждый бит своего первого операнда с соответствующим битом своего второго операнда. Если бит в одном из операндов равен 0, а бит в другом операнде равен 1, соответствующий бит результата устанавливается в 1. В противном случае соответствующий бит результата устанавливается в 0.) (C ++ / CLI и C ++ / CX). . В C альтернативное написание предоставляется в виде макроса в заголовке / permissive-
или / Za
необходим для включения альтернативного написания.
Пример
// expre_Bitwise_Exclusive_OR_Operator.cpp
// компилировать с помощью: / EHsc
// Продемонстрируем побитовое исключающее ИЛИ
#include
используя пространство имен std;
int main () {
беззнаковый короткий a = 0x5555; // шаблон 0101.б) << endl; // выводит шаблон "aaaa" 1010 ...
}
См. Также
Встроенные операторы C ++, приоритет и ассоциативность
Побитовая операция исключающее ИЛИ - онлайн-калькулятор
Операция двоичного исключающего ИЛИ битов двух целых чисел
Двоичная операция XOR
Эта функция выполняет побитовую операцию исключающего ИЛИ двух целых чисел.С помощью этой функции биты двух целых чисел объединяются двоичным исключающим ИЛИ.
Число можно вводить в шестнадцатеричном, десятичном, восьмеричном или двоичном формате.
Результат отображается в шестнадцатеричном, десятичном, восьмеричном и двоичном форматах.
|
Описание функции исключающего ИЛИ
Bitweise exklusive ODER, or kurz XOR Funktion, wird auf die Bitfolgen zweier ganzer Zahlen angewendet.Es wird die logische XOR-Operation auf jedem Paar korrespondierender Bits durchführt.
Das Ergebnisbit ist 1, Fall die zwei Bits unterschiedlich sind, und 0, drops sie gleich sind.
Функция побитового исключающего ИЛИ (XOR) применяется к битовым последовательностям двух целых чисел.
Биты одного числа подвергаются логической операции XOR с соответствующими битами другого числа.
Для каждой пары бит результирующий бит равен 0, если оба бита равны 0 или 1.Если один из обоих битов равен 1, бит результата устанавливается в 1.
Пример
В следующем примере биты двоичных чисел 11001100 и 11101 подвергаются операции XOR.
Результат 1010001.
|
C ++ Tutorial => ^ - побитовое исключающее ИЛИ (исключающее ИЛИ)
Пример
int a = 5; // 0101b (0x05)
int b = 9; // 1001b (0x09)
int c = a ^ b; // 1100b (0x0C)
std :: cout << "a =" << a << ", b =" << b << ", c =" << c << std :: endl;
Выход
a = 5, b = 9, c = 12
Почему
Побитовое XOR
(исключающее ИЛИ) работает на битовом уровне и использует следующую логическую таблицу истинности:
истина ИЛИ истина = ложь
истина ИЛИ ложь = истина
ложь ИЛИ ложь = ложь
Обратите внимание, что с операцией XOR true OR true = false
, где, как и с операциями true AND / OR true = true
, отсюда исключительный характер операции XOR. = Ь;
std :: cout << "a =" << a << ", b =" << b << "\ n";
Для производства вам нужно добавить чек, чтобы убедиться, что его можно использовать.c = ~ (a & c) & (a | c)
также в компиляторах 2015+ переменные могут быть назначены как двоичные:
int cn = 0b0111;
Оператор XOR Python: побитовый оператор в Python
Оператор XOR
в Python также известен как « исключающий или », который сравнивает два двоичных числа побитово. между двумя значениями, чтобы выполнить побитовое « исключающее или » для их двоичных представлений. Например, при использовании между двумя целыми числами оператор XOR возвращает целое число.
Теперь давайте посмотрим на базовый обзор побитовых операторов в Python.
Побитовые операторы Python
Побитовые операторы Python используются для выполнения побитовых вычислений над целыми числами. Сначала целые числа преобразуются в двоичный формат, а затем операции выполняются побитно, отсюда и название побитовые операторы.= b
print ('После замены:')
print ('Значение a:', a)
print ('Значение b:', b)
Выходные данные
Значение a: 21 Значение b: 19 После замены: Значение a: 19 Значение b: 21
Вот и все.
См. Также
Python Division
Python Square
Python sftp
Python Modulo
Python rstrip
XOR - волшебный побитовый оператор
Магический побитовый оператор - XOR - предоставляет новые подходы, о существовании которых вы даже не подозревали для решения конкретной проблемы.) оператор. Чтобы решить эту проблему, вам необходимо знать свойство двоичного вычитания.
Понимание битовых манипуляций предоставляет новые подходы, о существовании которых вы даже не подозревали, для решения конкретной проблемы. Давайте сделаем все необходимое, чтобы начать разработку этого побитового подхода.
В этой статье мы обсудим магические возможности побитового оператора XOR.
XOR - действительно удивительный оператор. Вы даже представить себе не можете, что это позволяет нам делать. Прежде чем увидеть, что он может делать, давайте пересмотрим то, что мы, возможно, уже знаем об операторе.0011 = 0110 = 6
Это была основная информация о XOR. Теперь давайте посмотрим, какими магическими способностями обладает оператор XOR! Я хотел бы объяснить их, указав несколько проблем раньше, которые помогут вам ясно понять свойства.
Возвращает крайнюю правую единицу в двоичном представлении числа.
Пример: Для 1010 вы должны выполнить некоторые операции, чтобы на выходе получить 0010. Для 1100 вы должны указать 0100. Аналогично для 0001 вы должны вернуть 0001. (x & (x - 1))
Единственный способ вы можете полностью понять, как работает вышеуказанное решение, попробовав его для разных двоичных чисел на листе бумаги.
(Если у вас есть опыт работы в сфере CS и вы понимаете все, что я говорил до сих пор, то поздравляю! Теперь вы уже знаете на 80% о мощной структуре данных под названием Fenwick Tree или Binary Indexed Tree. Вы можете посмотреть на это, чтобы узнать 20%, или дайте мне знать, если вы хотите, чтобы моя следующая статья была об этом.)
Интересно! не так ли? Давайте посмотрим еще на некоторые функции.
Для данного массива повторяющихся элементов ровно один элемент не повторяется. Вам нужно вернуть неповторяющийся элемент.arr [i] и сохраните результат в v для каждой итерации.Return v.
Итак, в качестве последнего вопроса я хотел бы дать вам довольно сложную задачу. Это не требует использования каких-либо новых свойств XOR, кроме упомянутых выше.
Напишите функцию для определения количества битов, необходимых для преобразования целого числа A в целое число B.
Ввод: 31, 14
Вывод: 2
Объяснение: У вас есть 31 (11111) и 14 (01110). Чтобы преобразовать 31 в 14, нам нужно перевернуть крайний левый бит и крайний правый бит 31.
Количество битов, необходимых для переворота, равно 2, поэтому мы возвращаем 2 в качестве ответа.
Входные данные: 12, 7
Выходные данные: 3
Я предлагаю вам попробовать реализовать это, прежде чем рассматривать решение ниже. Удачи!
Если вы чувствуете, что это помогло вам в чем-то, то поставьте лайк и подпишитесь на меня, чтобы узнать больше о компьютерных науках.
Решение:
Связанные истории
Теги
Присоединяйтесь к хакеру Полдень
Создайте бесплатную учетную запись, чтобы разблокировать свой собственный опыт чтения.
Что означает побитовое исключающее ИЛИ (исключающее ИЛИ)?
Я знаю, что это довольно старый пост, но я хотел упростить ответ, так как наткнулся на него, когда искал что-то еще.
XOR (исключающее ИЛИ / либо или) может быть переведено просто как включение / выключение.
Которая либо исключает (если существует), либо включает (если не существует) указанные биты.
Используя 4 бита (1111), мы получаем 16 возможных результатов от 0 до 15:
десятичный | двоичный | биты (развернутые)
0 | 0000 | 0
1 | 0001 | 1
2 | 0010 | 2
3 | 0011 | (1 + 2)
4 | 0100 | 4
5 | 0101 | (1 + 4)
6 | 0110 | (2 + 4)
7 | 0111 | (1 + 2 + 4)
8 | 1000 | 8
9 | 1001 | (1 + 8)
10 | 1010 | (2 + 8)
11 | 1011 | (1 + 2 + 8)
12 | 1100 | (4 + 8)
13 | 1101 | (1 + 4 + 8)
14 | 1110 | (2 + 4 + 8)
15 | 1111 | (1 + 2 + 4 + 8)
Десятичное значение слева от двоичного значения - это числовое значение, используемое в XOR и других побитовых операциях, которое представляет общее значение связанных битов.13) 4 и 8 являются членами 1 + 4 + 8 (13) удалить 4 + 8 = 1
- 2 не является членом 1 + 4 + 8 (13) добавить 2 = 1 + 2 (3)
Чтобы увидеть, как это работает, сначала вам нужно записать оба операнда в двоичном формате, потому что побитовые операции работают с отдельными битами.
Затем вы можете применить таблицу истинности для вашего конкретного оператора. Он воздействует на каждую пару битов, имеющих одинаковую позицию в двух операндах (одно и то же разрядное значение).x можно заменить на 0
(самообратное свойство). А любые 0
можно удалить (потому что это тождество).
Повторяйте как можно дольше. Любое число, которое встречается четное количество раз, имеет целое количество пар, поэтому все они становятся 0 и исчезают.
В конце концов у вас останется только один элемент, который встречается нечетное количество раз. Каждый раз, когда он появляется дважды, эти двое исчезают. В конце концов у вас остается один случай.
[обновить]
Обратите внимание, что это доказательство требует только определенных предположений об операции. В частности, предположим, что набор S с оператором .
имеет следующие свойства:
Ассоциативность: х. (y. z) = (x. y). z
для любых x
, y
и z
для S.
Идентификатор: существует единственный элемент e
, такой что e. х = х. e = x
для всех x
в S.
Закрытие: для любых x
и y
в S, x.y
также находится в S.
Самоинверсия: для любых x
в S, x. х = е
Как оказалось, нам не нужно предполагать коммутативность; мы можем это доказать:
(х. У). (x. y) = e (самообратным)
Икс . (у. х). y = e (по ассоциативности)
Икс . Икс . (у. х). у. у = х. е. y (умножьте обе стороны на x слева и y справа)
у. х = х. y (потому что x. x = y. y = e и е уходят)
Я сказал, что «вам не нужно ничего знать об отдельных битах».Я думал, что любой группы, удовлетворяющей этим свойствам, будет достаточно, и что такая группа не обязательно должна быть изоморфной целым числам при XOR.
Но @Steve Jessup доказал мою неправоту в комментариях. Если вы определите скалярное умножение на {0,1} как:
0 * х = 0
1 * х = х
... тогда эта структура удовлетворяет всем аксиомам векторного пространства над целыми числами по модулю 2.
Таким образом, любая такая структура изоморфна набору векторов битов при покомпонентном исключающем ИЛИ.
18.2.1: Побитовые операторы
18.2.1: Побитовые операторы
18.2.1: Побитовые операторы
[Этот раздел соответствует K&R Sec. 2.9]
Поразрядные операторы оперируют числами
(всегда целые числа)
как если бы они были
последовательности
двоичных разрядов
(что, конечно, внутри компьютера они
находятся).
Эти операторы будут наиболее разумными,
следовательно,
если мы рассматриваем целые числа как представленные в двоичном, восьмеричном или шестнадцатеричном формате
(базы 2, 8 или 16),
не десятичный (основание 10).Помнить,
вы можете использовать восьмеричные константы в C
добавив к ним дополнительный 0 (ноль),
и вы можете использовать шестнадцатеричные константы
добавив к ним префикс 0x
(или 0X).
Оператор &
выполняет побитовое И над двумя целыми числами.
Каждый бит в результате равен 1, только если
оба соответствующих бита в двух входных операндах равны 1.
Например, 0x56 и 0x32 - это 0x12,
потому что (в двоичном формате):
0 1 0 1 0 1 1 0 & 0 0 1 1 0 0 1 0 --------------- 0 0 0 1 0 0 1 0
The | (вертикальная черта) оператор
выполняет побитовое ИЛИ над двумя целыми числами.0 0 1 1 0 0 1 0
---------------
0 1 1 0 0 1 0 0
Оператор ~ (тильда)
выполняет побитовое дополнение для своего единственного целочисленного операнда.
(Следовательно, оператор ~ является унарным оператором,
нравиться !
и унарные операторы -, & и *.)
Дополнение числа означает изменение всех
От 0 бит до 1
и все от 1 до 0.
Например, для 16-битных целых чисел ~ 0x56 равно 0xffa9:
~ 0 0 0 0 0 0 0 0 0 1 0 1 0 1 1 0 ------------------------------- 1 1 1 1 1 1 1 1 1 0 1 0 1 0 0 1
Оператор <<
сдвигает свой первый операнд влево на некоторое количество бит
заданный вторым операндом,
заполнение новых 0 бит справа.Аналогично оператор >>
сдвигает свой первый операнд вправо.
Если первый операнд беззнаковый,
>> заполняет 0 бит слева,
но если первый операнд подписан,
>> может заполнить 1 бит, если старший бит уже равен 1.
(Такая неопределенность
это одна из причин, почему это обычно хорошая идея
использовать все беззнаковые операнды
при работе с побитовыми операторами.)
Например, 0x56 << 2 равно 0x158:
0 1 0 1 0 1 1 0 << 2 ------------------- 0 1 0 1 0 1 1 0 0 0
И 0x56 >> 1 - это 0x2b:
0 1 0 1 0 1 1 0 >> 1 --------------- 0 1 0 1 0 1 1
Для обоих операторов сдвига
биты, которые прокручиваются `` с конца '', отбрасываются;
они не оборачиваются.(Следовательно, 0x56 >> 3 - это 0x0a.)
Побитовые операторы будут иметь больше смысла
если мы посмотрим на некоторые из способов, которыми они обычно используются.
Мы можем использовать &, чтобы проверить, равен ли определенный бит 1 или нет.
Например, 0x56 и 0x40 - это 0x40,
но 0x32 и 0x40 - это 0x00:
0 1 0 1 0 1 1 0 0 0 1 1 0 0 1 0 & 0 1 0 0 0 0 0 0 & 0 1 0 0 0 0 0 0 --------------- --------------- 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Поскольку любой ненулевой результат считается истинным в C,
мы можем использовать выражение с участием & напрямую
чтобы проверить какое-то условие,
Например:
если (x & 0x04) сделать что-нибудь ;
(Если нам не нравилось тестирование с побитовым результатом,
мы могли бы эквивалентно сказать
если ((x & 0x04)! = 0).Дополнительные круглые скобки важны, как мы объясним ниже.)
Обратите внимание, что
значение 0x40
имеет ровно один бит в двоичном представлении,
что делает его полезным для тестирования
на наличие определенного бита.
Такое значение
часто называется -битной маской .
Часто мы определяем серию битовых масок,
все нацелены на разные биты,
а затем рассматривать одно целое значение как набор флагов .
`` Флаг '' - это состояние включено-выключено, да-нет,
поэтому нам нужен только один бит для его записи, а не 16 или 32 бит
(или более) int.Хранение набора флагов в одном int
делает больше, чем просто экономит место,
это также позволяет назначать сразу набор флагов
от одной флаговой переменной к другой,
используя обычный оператор присваивания =.
Например, если бы мы сделали эти определения:
#define DIRTY 0x01 #define OPEN 0x02 #define VERBOSE 0x04 #define RED 0x08 #define SEASICK 0x10
мы бы установили 5 разных бит
как отслеживание этих 5 различных условий
(`` грязный '', `` открытый '' и т. д.).
Если бы у нас была переменная
беззнаковые целочисленные флаги;
который содержал набор этих флагов,
мы могли бы написать тесты вроде
если (флаги и ГРЯЗНЫЕ) {/ * код для грязного случая * /}
если (! (флаги & ОТКРЫТЬ)) {/ * код для закрытого дела * /}
если (флаги и ГЛАГОЛ) {/ * код для подробного регистра * /} else {/ * код для скрытого случая * /}
Условие вроде if (флаги и DIRTY)
можно читать как
`` если установлен бит DIRTY ''.
Эти битовые маски также могут быть полезны для установки флагов .
Чтобы `` включить ГРЯЗНЫЙ бит '',
мы бы сказали
flags = флаги | ГРЯЗНЫЙ; / * устанавливаем бит DIRTY * /
Как бы нам немного `` выключиться ''?
Способ сделать это - оставить все, кроме той, которую мы выключаем,
если бы они уже были.
Мы делаем это с помощью операторов & и ~:
flags = flags & ~ DIRTY; / * очистить бит DIRTY * /
Это может быть легче увидеть, если мы посмотрим на это в двоичном формате.
Если биты DIRTY, RED и SEASICK
были уже включены,
flags будет 0x19, и у нас будет
0 0 0 1 1 0 0 1 & 1 1 1 1 1 1 1 0 --------------- 0 0 0 1 1 0 0 0
Как вы видете,
как | оператор при включении бит
и оператор & (плюс ~) при отключении битов
не действуют, если целевой бит уже был включен или выключен соответственно.= ГЛАГОЛ; / * переключить бит VERBOSE * /
Мы также можем использовать побитовые операторы для извлечения
подмножества бит из середины
целое число.
Например,
для извлечения предпоследней шестнадцатеричной `` цифры ''
мы могли бы использовать
(я & 0xf0) >> 4
Если бы я был 0x56, у нас было бы:
я 0 1 0 1 0 1 1 0 & 0x56 & 1 1 1 1 0 0 0 0 --------------- 0 1 0 1 0 0 0 0
и сдвинув этот результат вправо на 4 бита
дает нам 0 1 0 1,
или 5,
как мы хотели.
Замена
(или перезапись)
подмножество бит
немного сложнее;
мы должны сначала использовать & и ~
чтобы очистить все биты назначения,
затем используйте << и | в `` ИЛИ в ''
новые биты.
операторы низкие, обычно ниже, чем хотелось бы.)
ниже, чем ==,! =,
<<, и >>,
выражения вроде
if (a & 0x04! = 0) / * НЕПРАВИЛЬНО * /
а также
i & 0xf0 >> 4 / * НЕПРАВИЛЬНО * /
будет ли не работать должным образом;
эти два последних будут эквивалентны
если (а & (0x04! = 0)) я & (0xf0 >> 4)
и не будет выполнять требуемый нам битовый тест или извлечение подмножества.
[Остальная часть этого раздела несколько сложна и может быть пропущена.]
Из-за природы арифметики с основанием 2,
оказывается, что сдвиг влево и сдвиг вправо
эквивалентны умножению и делению на два.Эти операции эквивалентны по той же причине, что и
Прибавка нулей справа от числа в базе 10
это то же самое, что и умножение на 10,
а удаление цифр справа аналогично делению на 10.
Вы можете убедить себя, что
0x56 << 2
совпадает с 0x56 * 4,
и это
0x56 >> 1
совпадает с 0x56 / 2.
Это также тот случай, когда маскирование всех, кроме младших битов
то же самое, что и получение остатка;
Например,
0x56 и 0x07
совпадает с 0x56% 8.
Поэтому некоторые программисты используют
<<, >> и &
в предпочтении к
*, /, а также %
когда задействованы степени двойки,
на том основании, что побитовые операторы `` более эффективны.''
Обычно об этом не стоит беспокоиться,
потому что большинство компиляторов достаточно умны
в любом случае выполнить эту оптимизацию
(то есть, если вы напишете x * 4,
компилятор может сам сгенерировать инструкцию сдвига влево),
они не всегда удобочитаемы,
и они не всегда верны для отрицательных чисел.
Проблема отрицательных чисел, кстати,
объясняет, почему оператор сдвига вправо >>
не определено точно
когда старший бит сдвигаемого значения равен 1.Для значений со знаком
если старший бит равен 1,
число отрицательное.
(Это верно для дополнения 1, дополнения 2,
и представления величины знака.)
Если вы использовали правый сдвиг для реализации разделения,
вы хотите, чтобы отрицательное число оставалось отрицательным,
поэтому на некоторых компьютерах
под некоторыми компиляторами,
когда вы сдвигаете знаковое значение вправо
а старший бит равен 1,
новый
Слева сдвигается 1 бит вместо 0.
Однако на это нельзя полагаться,
потому что не все компьютеры и компиляторы реализуют правый сдвиг таким образом.В любом слючае,
сдвиг отрицательных чисел вправо
(даже если распространяется старший бит 1)
дает неправильный ответ, если есть остаток:
в дополнении до 2, 16-битная арифметика, -15 равно 0xfff1,
так -15 >> 1 может дать вам
0xfff8shifted
что -8.
Но целочисленное деление должно отбрасывать остаток,
поэтому -15 / 2 даст вам -7.
(Если вы не видите, как работает смена,
0xfff1 - это 1111111111110001 2 и
0xfff8 - это 1111111111111000 2 .Младший бит 1 сдвинулся вправо,
но поскольку старший бит был 1,
1 сместился слева.)
Читайте последовательно:
предыдущий
следующий
вверх
Топ
Эта страница Стива Саммита
// Авторское право 1996-1999 гг.
// отправить отзыв по электронной почте
.