<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=195.209.230.212&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=195.209.230.212&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/195.209.230.212"/>
		<updated>2026-05-19T06:26:05Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D0%B1%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8&amp;diff=72864</id>
		<title>Побитовые операции</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9F%D0%BE%D0%B1%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8&amp;diff=72864"/>
				<updated>2020-03-10T09:09:08Z</updated>
		
		<summary type="html">&lt;p&gt;195.209.230.212: /* Побитовые сдвиги, поправлены символы операторов */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Побитовые операции''' (англ. ''bitwise operations'') — операции, производимые над цепочками битов. Выделяют два типа побитовых операций: [[Определение булевой функции | логические операции]] и побитовые сдвиги.&lt;br /&gt;
==Принцип работы==&lt;br /&gt;
===Логические побитовые операции===&lt;br /&gt;
Битовые операторы И &amp;lt;tex&amp;gt;(AND,\ \&amp;amp;)&amp;lt;/tex&amp;gt;, ИЛИ &amp;lt;tex&amp;gt;(OR,\ \mid)&amp;lt;/tex&amp;gt;, НЕ &amp;lt;tex&amp;gt;(NOT,\ \sim)&amp;lt;/tex&amp;gt; и исключающее ИЛИ &amp;lt;tex&amp;gt;(XOR,\ $\textasciicircum$,\ \oplus)&amp;lt;/tex&amp;gt; используют те же таблицы истинности, что и их логические эквиваленты.&lt;br /&gt;
====Побитовое И====&lt;br /&gt;
Побитовое И используется для выключения битов. Любой бит, установленный в &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, вызывает установку соответствующего бита результата также в &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 !rowspan=2|&amp;amp;&lt;br /&gt;
 |-&lt;br /&gt;
 |11001010 &amp;lt;br&lt;br /&gt;
 /&amp;gt;11100010&lt;br /&gt;
 |-&lt;br /&gt;
 |||11000010&lt;br /&gt;
 |}&lt;br /&gt;
====Побитовое ИЛИ====&lt;br /&gt;
Побитовое ИЛИ используется для включения битов. Любой бит, установленный в &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, вызывает установку соответствующего бита результата также в &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;.&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 !rowspan=2| |&lt;br /&gt;
 |-&lt;br /&gt;
 |11001010 &amp;lt;br&lt;br /&gt;
 /&amp;gt;11100010&lt;br /&gt;
 |-&lt;br /&gt;
 |||11101010&lt;br /&gt;
 |}&lt;br /&gt;
====Побитовое НЕ====&lt;br /&gt;
Побитовое НЕ инвертирует состояние каждого бита исходной переменной.&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 !rowspan=2| ~&lt;br /&gt;
 |-&lt;br /&gt;
 |11001010&lt;br /&gt;
 |-&lt;br /&gt;
 |||00110101&lt;br /&gt;
 |}&lt;br /&gt;
====Побитовое исключающее ИЛИ====&lt;br /&gt;
Исключающее ИЛИ устанавливает значение бита результата в &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, если значения в соответствующих битах исходных переменных различны.&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 !rowspan=2| ^&lt;br /&gt;
 |-&lt;br /&gt;
 |11001010 &amp;lt;br&lt;br /&gt;
 /&amp;gt;11100010&lt;br /&gt;
 |-&lt;br /&gt;
 |||00101000&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
===Побитовые сдвиги===&lt;br /&gt;
Операторы сдвига &amp;lt;tex&amp;gt;&amp;lt;&amp;lt;&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;{&amp;gt;&amp;gt;}&amp;lt;/tex&amp;gt; сдвигают биты в переменной влево или вправо на указанное число. При этом на освободившиеся позиции устанавливаются нули (кроме сдвига вправо отрицательного числа, в этом случае на свободные позиции устанавливаются единицы, так как числа представляются в [[Представление целых чисел: прямой код, код со сдвигом, дополнительный код #Дополнительный код (дополнение до двух) | двоичном дополнительном коде]] и необходимо поддерживать знаковый бит).&lt;br /&gt;
&lt;br /&gt;
Сдвиг влево может применяться для умножения числа на два, сдвиг вправо — для деления.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 x = 7         &amp;lt;font color = green&amp;gt;// 00000111 (7)&amp;lt;/font&amp;gt;&lt;br /&gt;
 x = x &amp;gt;&amp;gt; 1    &amp;lt;font color = green&amp;gt;// 00000011 (3)&amp;lt;/font&amp;gt;&lt;br /&gt;
 x = x &amp;lt;&amp;lt; 1    &amp;lt;font color = green&amp;gt;// 00000110 (6)&amp;lt;/font&amp;gt;&lt;br /&gt;
 x = x &amp;lt;&amp;lt; 5    &amp;lt;font color = green&amp;gt;// 11000000 (-64)&amp;lt;/font&amp;gt;&lt;br /&gt;
 x = x &amp;gt;&amp;gt; 2    &amp;lt;font color = green&amp;gt;// 11110000 (-16)&amp;lt;/font&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В языке программирования Java существует также оператор беззнакового битового сдвига вправо &amp;lt;tex&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;lt;/tex&amp;gt;. При использовании этого оператора на освободившиеся позиции всегда устанавливаются нули.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 x = 7          &amp;lt;font color = green&amp;gt;// 00000111 (7)&amp;lt;/font&amp;gt;&lt;br /&gt;
 x = x &amp;lt;&amp;lt; 5     &amp;lt;font color = green&amp;gt;// 11100000 (-32)&amp;lt;/font&amp;gt;&lt;br /&gt;
 x = x &amp;gt;&amp;gt;&amp;gt; 2    &amp;lt;font color = green&amp;gt;// 00111000 (56)&amp;lt;/font&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Применение==&lt;br /&gt;
===Сложные операции===&lt;br /&gt;
====Определение знака числа====&lt;br /&gt;
Пусть дано число &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Поскольку при сдвиге вправо на освобождающиеся позиции устанавливается бит знака, знак числа &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; можно определить, выполнив сдвиг вправо на всю длину переменной:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int32''' getSign(x: '''int32'''):&lt;br /&gt;
     '''if''' x != 0:&lt;br /&gt;
         mask = 1&lt;br /&gt;
     '''else''':&lt;br /&gt;
         mask = 0&lt;br /&gt;
 &lt;br /&gt;
     '''return''' mask | (x &amp;gt;&amp;gt; 31)    &amp;lt;font color = green&amp;gt;// результатом будет -1, 0, или +1 &lt;br /&gt;
                                // для отрицательного, равного нулю и положительного числа x соответственно&amp;lt;/font&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Используя побитовые операции можно также узнать, различны ли знаки двух переменных &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt;. Если числа имеют различный знак, то результат операции XOR, произведенной над их знаковыми битами, будет единицей. Поэтому неравенство &amp;lt;tex&amp;gt;(x \oplus y) &amp;lt; 0&amp;lt;/tex&amp;gt; будет верно в том случае, если числа &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; разного знака.&lt;br /&gt;
&lt;br /&gt;
====Вычисление модуля числа без использования условного оператора====&lt;br /&gt;
Пусть дано число &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Если &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; положительно, то &amp;lt;tex&amp;gt;mask = 0&amp;lt;/tex&amp;gt;, и &amp;lt;tex&amp;gt;(x + mask) \oplus mask = x&amp;lt;/tex&amp;gt;. В случае, если &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; отрицательно, &amp;lt;tex&amp;gt;mask = -1&amp;lt;/tex&amp;gt;. Тогда получается, что мы работаем с числом &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; так, как будто оно представлено в [[Представление целых чисел: прямой код, код со сдвигом, дополнительный код #Код со сдвигом |&lt;br /&gt;
коде со сдвигом]] с тем отличием, что у нас знаковый бит принимает значение &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; для отрицательных чисел, а &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; {{---}} для положительных.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int32''' abs1(x: '''int32'''):&lt;br /&gt;
     mask = x &amp;gt;&amp;gt; 31&lt;br /&gt;
     '''return''' (x + mask) '''XOR''' mask&lt;br /&gt;
 &lt;br /&gt;
 '''int32''' abs2(x: '''int32'''):&lt;br /&gt;
     mask = x &amp;gt;&amp;gt; 31&lt;br /&gt;
     '''return''' (x + mask) '''XOR''' mask&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Нахождение минимума и максимума из двух чисел без использования условного оператора====&lt;br /&gt;
Этот способ корректен только если можно утверждать, что величина &amp;lt;tex&amp;gt;(x - y)&amp;lt;/tex&amp;gt; лежит между граничными значениями типа int.&lt;br /&gt;
&lt;br /&gt;
Пусть даны числа &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;y&amp;lt;/tex&amp;gt; разрядности &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;. Тогда если &amp;lt;tex&amp;gt;x &amp;lt; y&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;((x - y) &amp;gt;&amp;gt; (n - 1)) = -1&amp;lt;/tex&amp;gt;, а если &amp;lt;tex&amp;gt;x \geqslant y&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;((x - y) &amp;gt;&amp;gt; (n - 1)) = 0&amp;lt;/tex&amp;gt;. Выражение &amp;lt;tex&amp;gt;((x - y) \&amp;amp; ((x - y) &amp;gt;&amp;gt; (n - 1))&amp;lt;/tex&amp;gt; принимает значение &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;, если &amp;lt;tex&amp;gt;x \geqslant y&amp;lt;/tex&amp;gt;, и &amp;lt;tex&amp;gt;(x - y)&amp;lt;/tex&amp;gt;, если &amp;lt;tex&amp;gt;x &amp;lt; y&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int32''' min(x, y: '''int32'''):&lt;br /&gt;
     '''return''' y + ((x - y) &amp;amp; ((x - y) &amp;gt;&amp;gt; 31))&lt;br /&gt;
 &lt;br /&gt;
 '''int32''' max(x, y: '''int32'''):&lt;br /&gt;
     '''return''' x - ((x - y) &amp;amp; ((x - y) &amp;gt;&amp;gt; 31))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Проверка на то, является ли число степенью двойки====&lt;br /&gt;
Пусть дано число &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Тогда, если результатом выражения &amp;lt;tex&amp;gt;(x\ \&amp;amp;\&amp;amp;\ !(x\ \&amp;amp;\ (x - 1)))&amp;lt;/tex&amp;gt; является единица, то число &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; {{---}} степень двойки.&lt;br /&gt;
 &lt;br /&gt;
Правая часть выражения &amp;lt;tex&amp;gt;(!(x\ \&amp;amp;\ (x - 1)))&amp;lt;/tex&amp;gt; будет равна единице, только если число &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; равно &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; или является степенью двойки. Если число &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; является степенью двойки, то в двоичной системе счисления оно представляется следующим образом: &amp;lt;tex&amp;gt;1\underbrace{0\dots0}_{n}&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; {{---}} показатель степени. Соответственно, выражение &amp;lt;tex&amp;gt;(x - 1)&amp;lt;/tex&amp;gt; будет иметь вид &amp;lt;tex&amp;gt;\underbrace{1\dots1}_{n}&amp;lt;/tex&amp;gt;, и &amp;lt;tex&amp;gt;x\ \&amp;amp;\ (x - 1)&amp;lt;/tex&amp;gt; равно &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Операция логического И в данном выражении отсекает тот случай, когда &amp;lt;tex&amp;gt;(x = 0)&amp;lt;/tex&amp;gt; и не является степенью двойки, но при этом правая часть &amp;lt;tex&amp;gt;(!(x\ \&amp;amp;\ (x - 1)))&amp;lt;/tex&amp;gt; равна единице.&lt;br /&gt;
&lt;br /&gt;
====Нахождение младшего единичного бита====&lt;br /&gt;
Пусть дано число &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; и необходимо узнать его младший единичный бит.&lt;br /&gt;
&lt;br /&gt;
Применим к числу &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; побитовое отрицание, чтобы инвертировать значения всех его бит, а затем прибавим к полученному числу единицу. У результата первая часть (до младшего единичного бита) не совпадает с исходным числом &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, а вторая часть совпадает. Применив побитовое И к этим двум числам, получим степень двойки, соответствующую младшему единичному биту исходного числа &amp;lt;tex&amp;gt;(x\ \&amp;amp;\ (\sim x + 1))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
К такому же результату можно прийти, если сначала отнять от числа &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; единицу, чтобы обнулить его младший единичный бит, а все последующие разряды обратить в &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt;, затем инвертировать результат и применить побитовое И с исходным числом &amp;lt;tex&amp;gt;(x\ \&amp;amp;\ \sim (x - 1))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Нахождение старшего единичного бита====&lt;br /&gt;
Пусть дано число &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; и необходимо узнать его старший единичный бит.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим некоторое число, представим его как &amp;lt;tex&amp;gt;0\dots01b \dots b&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;b&amp;lt;/tex&amp;gt; {{---}} любое значение бита. Тогда, если совершить битовый сдвиг этого числа вправо на &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; и произвести побитовое ИЛИ результата сдвига и исходного числа, мы получим результат &amp;lt;tex&amp;gt;0\dots011b \dots b&amp;lt;/tex&amp;gt;. Если мы повторим эту последовательность действий над полученным числом, но устроим сдвиг на &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt;, то получим &amp;lt;tex&amp;gt;0\dots01111b \dots b&amp;lt;/tex&amp;gt;. При каждой следующей операции будем увеличивать модуль сдвига до следующей степени двойки. После некоторого количества таких операций (зависит от разрядности числа) мы получим число вида &amp;lt;tex&amp;gt;0\dots01\dots1&amp;lt;/tex&amp;gt;. Тогда результатом выполнения действий &amp;lt;tex&amp;gt;x - (x \texttt{ &amp;gt;&amp;gt; }1)&amp;lt;/tex&amp;gt; будет число, состоящее только из старшего бита исходного числа.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int32''' greatestBit(x: '''int32'''):&lt;br /&gt;
     power = 1&lt;br /&gt;
     '''for''' i = 1 &amp;lt;tex&amp;gt; \ldots\log_2{32}&amp;lt;/tex&amp;gt;:&lt;br /&gt;
         x |= x &amp;gt;&amp;gt; power&lt;br /&gt;
         power &amp;lt;&amp;lt;= 1&lt;br /&gt;
     '''return''' x - (x &amp;gt;&amp;gt; 1)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Циклический сдвиг====&lt;br /&gt;
Пусть дано число &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; и надо совершить циклический сдвиг его битов на величину &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Желаемый результат можно получить, если объединить числа, полученные при выполнении обычного битового сдвига в желаемую сторону на &amp;lt;tex&amp;gt;d&amp;lt;/tex&amp;gt; и в противоположном направлении на разность между разрядностью числа и величиной сдвига. Таким образом, мы сможем поменять местами начальную и конечную части числа.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int32''' rotateLeft(x, d: '''int32'''):&lt;br /&gt;
     '''return''' (x &amp;lt;&amp;lt; d) | (x &amp;gt;&amp;gt;&amp;gt; (32 - d))&lt;br /&gt;
 &lt;br /&gt;
 '''int32''' rotateRight(x, d: '''int32'''):&lt;br /&gt;
     '''return''' (x &amp;gt;&amp;gt;&amp;gt; d) | (x &amp;lt;&amp;lt; (32 - d))&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Подсчет количества единичных битов====&lt;br /&gt;
Для подсчета количества единичных битов в числе &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; можно воспользоваться следующим алгоритмом:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;font color = green&amp;gt;// Для чисел других разрядностей необходимо использовать соответствующие константы.&amp;lt;/font&amp;gt; &lt;br /&gt;
 '''int16''' setBitsNumber(x: '''int16'''):&lt;br /&gt;
     x = x - ((x &amp;gt;&amp;gt;&amp;gt; 1) &amp;amp; 0x5555)&lt;br /&gt;
     x = (x &amp;amp; 0x3333) + ((x &amp;gt;&amp;gt;&amp;gt; 2) &amp;amp; 0x3333)&lt;br /&gt;
     x = (x + (x &amp;gt;&amp;gt;&amp;gt; 4)) &amp;amp; 0x0F0F&lt;br /&gt;
     '''return''' (x * 0x0101) &amp;gt;&amp;gt;&amp;gt; 8&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поскольку &amp;lt;tex&amp;gt;5555_{16}&amp;lt;/tex&amp;gt; равно &amp;lt;tex&amp;gt;01010101 01010101_{2}&amp;lt;/tex&amp;gt;, результатом операции &amp;lt;tex&amp;gt;x\ \&amp;amp;\ 5555_{16}&amp;lt;/tex&amp;gt; является число, в котором все нечетные биты соответствуют нечетным битам числа &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Аналогично, результатом операции &amp;lt;tex&amp;gt;(x\ \texttt{&amp;gt;&amp;gt;&amp;gt;}\ 1)\ \&amp;amp;\ 5555_{16}&amp;lt;/tex&amp;gt; является число, в котором все нечетные биты соответствуют четным битам &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;. Четные биты результата в обоих случаях равны нулю.&lt;br /&gt;
&lt;br /&gt;
Мысленно разобьем двоичную запись нашего числа &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt; на группы по &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; бита. Результатом операции &amp;lt;tex&amp;gt;x\ \&amp;amp;\ 5555_{16} + (x\ \texttt{&amp;gt;&amp;gt;&amp;gt;}\ 1)\ \&amp;amp;\ 5555_{16}&amp;lt;/tex&amp;gt; будет такое число, что если разбить его двоичную запись на группы по два бита, значение каждой группы соответствует количеству единичных битов в соответствующей паре битов числа &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Аналогично, число &amp;lt;tex&amp;gt;3333_{16}&amp;lt;/tex&amp;gt; равно &amp;lt;tex&amp;gt;00110011 00110011_{2}&amp;lt;/tex&amp;gt; и операция &amp;lt;tex&amp;gt;x = (x\ \&amp;amp;\ 3333_{16}) + (x\ \texttt{&amp;gt;&amp;gt;&amp;gt;}\ 2\ \&amp;amp;\ 3333_{16})&amp;lt;/tex&amp;gt;, примененная к результату, полученному на первом этапе, выполняет подсчет количества единичных битов в блоках по &amp;lt;tex&amp;gt;4&amp;lt;/tex&amp;gt;. В свою очередь, число &amp;lt;tex&amp;gt;\texttt{0F0F}_{16}&amp;lt;/tex&amp;gt; равно &amp;lt;tex&amp;gt;00001111 00001111_{2}&amp;lt;/tex&amp;gt; и операция &amp;lt;tex&amp;gt;x = (x\ \&amp;amp;\ \texttt{0F0F}_{16}) + (x\ \texttt{&amp;gt;&amp;gt;&amp;gt;}\ 4\ \&amp;amp;\ \texttt{0F0F}_{16})&amp;lt;/tex&amp;gt; позволяет подсчитать число единичных бит в блоках по &amp;lt;tex&amp;gt;8&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Теперь необходимо просуммировать числа, записанные в блоках по &amp;lt;tex&amp;gt;8&amp;lt;/tex&amp;gt; битов, чтобы получить искомую величину. Это можно сделать, домножив результат на &amp;lt;tex&amp;gt;0101_{16}&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;(1 00000001_{2})&amp;lt;/tex&amp;gt;. Ответ на задачу будет находиться в первых восьми битах произведения. Выполнив сдвиг вправо на &amp;lt;tex&amp;gt;8&amp;lt;/tex&amp;gt; (для шестнадцатибитных чисел), мы получим долгожданный ответ.&lt;br /&gt;
&lt;br /&gt;
Подведем итог:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''int16''' setBitsNumber(x: '''int16'''):&lt;br /&gt;
     x = (x &amp;amp; 0x5555) + ((x &amp;gt;&amp;gt;&amp;gt; 1) &amp;amp; 0x5555)&lt;br /&gt;
     x = (x &amp;amp; 0x3333) + ((x &amp;gt;&amp;gt;&amp;gt; 2) &amp;amp; 0x3333)&lt;br /&gt;
     x = (x &amp;amp; 0x0F0F) + ((x &amp;gt;&amp;gt;&amp;gt; 4) &amp;amp; 0x0F0F)&lt;br /&gt;
     '''return''' (x * 0x0101) &amp;gt;&amp;gt;&amp;gt; 8&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Заметим, что операция &amp;lt;tex&amp;gt;x\ \&amp;amp;\ 55_{16} + (x\ \texttt{&amp;gt;&amp;gt;&amp;gt;}\ 1)\ \&amp;amp;\ 55_{16}&amp;lt;/tex&amp;gt; равносильна операции &amp;lt;tex&amp;gt;x - (x\ \texttt{&amp;gt;&amp;gt;&amp;gt;}\ 1)\ \&amp;amp;\ 55_{16}&amp;lt;/tex&amp;gt;, в чем легко убедиться, рассмотрев все числа из двух бит.&lt;br /&gt;
&lt;br /&gt;
В свою очередь, операцию &amp;lt;tex&amp;gt;(x\ \&amp;amp;\ \texttt{0F0F}_{16}) + ((x\ \texttt{&amp;gt;&amp;gt;&amp;gt;}\ 4)\ \&amp;amp;\ \texttt{0F0F}_{16})&amp;lt;/tex&amp;gt; можно заменить на &amp;lt;tex&amp;gt;(x + (x\ \texttt{&amp;gt;&amp;gt;&amp;gt;}\ 4))\ \&amp;amp;\ \texttt{0F0F}_{16}&amp;lt;/tex&amp;gt;. Эта замена не повлияет на результат, так как максимальное значение в любой группе из четырех битов данного числа равно четырем, то есть требует только трех битов для записи, и выполнение суммирования не повлечет за собой переполнения и выхода за пределы четверок.&lt;br /&gt;
&lt;br /&gt;
Таким образом, мы получили код, приведенный в начале раздела.&lt;br /&gt;
&lt;br /&gt;
====Разворот битов====&lt;br /&gt;
Чтобы получить биты числа &amp;lt;tex&amp;gt;x&amp;lt;/tex&amp;gt;, записанные в обратном порядке, применим следующий алгоритм.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 &amp;lt;font color = green&amp;gt;// Для чисел других разрядностей нужны соответствующие константы.&amp;lt;/font&amp;gt;&lt;br /&gt;
 '''int16''' reverseBits(x: '''int16'''):&lt;br /&gt;
     x = ((x &amp;amp; 0x5555) &amp;lt;&amp;lt; 1) | ((x &amp;gt;&amp;gt;&amp;gt; 1) &amp;amp; 0x5555)  &amp;lt;font color = green&amp;gt;// Четные и нечетные биты поменялись местами.&amp;lt;/font&amp;gt;&lt;br /&gt;
     x = ((x &amp;amp; 0x3333) &amp;lt;&amp;lt; 2) | ((x &amp;gt;&amp;gt;&amp;gt; 2) &amp;amp; 0x3333)  &amp;lt;font color = green&amp;gt;// Биты &amp;quot;перетасовываются&amp;quot; группами по два.&amp;lt;/font&amp;gt;&lt;br /&gt;
     x = ((x &amp;amp; 0x0F0F) &amp;lt;&amp;lt; 4) | ((x &amp;gt;&amp;gt;&amp;gt; 4) &amp;amp; 0x0F0F)  &amp;lt;font color = green&amp;gt;// Биты &amp;quot;перетасовываются&amp;quot; группами по четыре.&amp;lt;/font&amp;gt;&lt;br /&gt;
     x = ((x &amp;amp; 0x00FF) &amp;lt;&amp;lt; 8) | ((x &amp;gt;&amp;gt;&amp;gt; 8) &amp;amp; 0x00FF)  &amp;lt;font color = green&amp;gt;// Биты &amp;quot;перетасовываются&amp;quot; группами по восемь.&amp;lt;/font&amp;gt;&lt;br /&gt;
     '''return''' x&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Более подробно про то, что за константы выбраны для данного алгоритма, можно прочитать в разделе [[Побитовые_операции#Подсчет_количества_единичных_битов | подсчет количества единичных битов]].&lt;br /&gt;
&lt;br /&gt;
===Применение для решения задач===&lt;br /&gt;
====Работа с битовыми масками====&lt;br /&gt;
Для работы с подмножествами удобно использовать битовые маски. Применяя побитовые операции легко сделать следующее: найти дополнение &amp;lt;tex&amp;gt;(\sim mask)&amp;lt;/tex&amp;gt;, пересечение &amp;lt;tex&amp;gt;(mask_1\ \&amp;amp;\ mask_2)&amp;lt;/tex&amp;gt;, объединение &amp;lt;tex&amp;gt;(mask_1 \mid mask_2)&amp;lt;/tex&amp;gt; множеств, установить бит по номеру &amp;lt;tex&amp;gt;(mask \mid (1\ \texttt{&amp;lt;&amp;lt;}\ x))&amp;lt;/tex&amp;gt;, снять бит по номеру &amp;lt;tex&amp;gt;(mask\ \&amp;amp;\ \sim(1\ \texttt{&amp;lt;&amp;lt;}\ x))&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Битовые маски используются, например, при решении некоторых задач&amp;lt;ref&amp;gt;[[Гамильтоновы графы #Задача о коммивояжере| Динамическое программирование по подмножествам (по маскам)]]&amp;lt;/ref&amp;gt; [[Динамическое программирование | динамического программирования]].&lt;br /&gt;
&lt;br /&gt;
====Алгоритм Флойда====&lt;br /&gt;
{{main|Алгоритм Флойда}}&lt;br /&gt;
'''Алгоритм Флойда–Уоршелла''' (англ. ''the Floyd–Warshall algorithm'') {{---}}  алгоритм для нахождения длин кратчайших путей между всеми парами вершин во взвешенном ориентированном графе. Работает корректно, если в графе нет циклов отрицательной величины, а если же такой цикл есть, позволяет найти хотя бы один такой цикл. Асимптотическая сложность алгоритма &amp;lt;tex&amp;gt; \Theta(n^3) &amp;lt;/tex&amp;gt;, также требует &amp;lt;tex&amp;gt; \Theta(n^2) &amp;lt;/tex&amp;gt; памяти.&lt;br /&gt;
&lt;br /&gt;
====Дерево Фенвика====&lt;br /&gt;
{{main|Дерево Фенвика}}&lt;br /&gt;
'''Дерево Фенвика''' (англ. ''Binary indexed tree'') {{---}}  структура данных, которая может выполнять следующие операции:&lt;br /&gt;
* изменять значение любого элемента в массиве,&lt;br /&gt;
* выполнять некоторую [[Ассоциативная_операция |ассоциативную]], [[Абелева_группа |коммутативную]], [[Группа |обратимую операцию]] &amp;lt;tex&amp;gt; \circ &amp;lt;/tex&amp;gt; на отрезке &amp;lt;tex&amp;gt; [i, j] &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данная структура требует  &amp;lt;tex&amp;gt; O(n) &amp;lt;/tex&amp;gt; памяти, а выполнение каждой операции происходит за &amp;lt;tex&amp;gt; O(\log n) &amp;lt;/tex&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Функция, позволяющая делать операции вставки и изменения элемента за &amp;lt;tex&amp;gt; O(\log n) &amp;lt;/tex&amp;gt;, задается следующей формулой &amp;lt;tex&amp;gt; F(i) = (i \And (i + 1)) &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Пусть дан массив &amp;lt;tex&amp;gt; A = [a_0, a_1, \ldots, a_{n - 1}]&amp;lt;/tex&amp;gt;.  Деревом Фенвика  называется  массив &amp;lt;tex&amp;gt; T &amp;lt;/tex&amp;gt; из &amp;lt;tex&amp;gt; n &amp;lt;/tex&amp;gt; элементов: &amp;lt;tex&amp;gt; T_i = \sum\limits_{k = F(i)}^{i} a_k&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt; i = 0\ldots n - 1 &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; F(i) &amp;lt;/tex&amp;gt; — функция, которую мы определили ранее.&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Определение булевой функции]]&lt;br /&gt;
* [[Сумматор]]&lt;br /&gt;
* [[Триггеры]]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [http://www.c-cpp.ru/books/bitovye-operatory Онлайн справочник программиста на С и С++]&lt;br /&gt;
* [http://developer.alexanderklimov.ru/android/java/bitwise.php Побитовые операторы]&lt;br /&gt;
* [https://graphics.stanford.edu/~seander/bithacks.html Bit Twiddling Hacks by Sean Eron Anderson]&lt;br /&gt;
* [https://habrahabr.ru/post/93172/ Habrahabr {{---}} Алгоритмы поиска старшего бита]&lt;br /&gt;
* [https://yesteapea.wordpress.com/2013/03/03/counting-the-number-of-set-bits-in-an-integer/ STP's blog {{---}} Counting the number of set bits in an integer]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Булевы функции ]]&lt;/div&gt;</summary>
		<author><name>195.209.230.212</name></author>	</entry>

	</feed>