HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-21
1 <p><a>#подборки</a></p>
1 <p><a>#подборки</a></p>
2 <ul><li>1 июл 2024</li>
2 <ul><li>1 июл 2024</li>
3 <li>0</li>
3 <li>0</li>
4 </ul><h2>Основные логические (битовые) операции: что это и как они работают</h2>
4 </ul><h2>Основные логические (битовые) операции: что это и как они работают</h2>
5 <p>Учимся умножать и складывать логически.</p>
5 <p>Учимся умножать и складывать логически.</p>
6 <p>Иллюстрация: Оля Ежак для Skillbox Media</p>
6 <p>Иллюстрация: Оля Ежак для Skillbox Media</p>
7 <p>Онлайн-журнал для тех, кто влюблён в код и информационные технологии. Пишем для айтишников и об айтишниках.</p>
7 <p>Онлайн-журнал для тех, кто влюблён в код и информационные технологии. Пишем для айтишников и об айтишниках.</p>
8 <p><strong>Логические (битовые) операции</strong> - это действия, которые программисты используют для работы с битами. Таких операций существует несколько: AND (И), OR (ИЛИ), XOR (исключающее ИЛИ), NOT (НЕ), а также побитовые сдвиги влево и вправо. Ещё существуют операторы NAND и NOR, но они не относятся к основным, поэтому в этой статье рассматривать их не будем.</p>
8 <p><strong>Логические (битовые) операции</strong> - это действия, которые программисты используют для работы с битами. Таких операций существует несколько: AND (И), OR (ИЛИ), XOR (исключающее ИЛИ), NOT (НЕ), а также побитовые сдвиги влево и вправо. Ещё существуют операторы NAND и NOR, но они не относятся к основным, поэтому в этой статье рассматривать их не будем.</p>
9 <p>Операции с логическими значениями впервые описал математик Джордж Буль - отсюда в языках программирования появилось ключевое слово boolean (bool), которое обозначает тип данных для хранения логического битового значения. Оно может быть равно 1 (истина) или 0 (ложь).</p>
9 <p>Операции с логическими значениями впервые описал математик Джордж Буль - отсюда в языках программирования появилось ключевое слово boolean (bool), которое обозначает тип данных для хранения логического битового значения. Оно может быть равно 1 (истина) или 0 (ложь).</p>
10 <ul><li><a>Операция XOR (исключающее ИЛИ)</a></li>
10 <ul><li><a>Операция XOR (исключающее ИЛИ)</a></li>
11 <li><a>Операция AND (И)</a></li>
11 <li><a>Операция AND (И)</a></li>
12 <li><a>Операция OR (ИЛИ)</a></li>
12 <li><a>Операция OR (ИЛИ)</a></li>
13 <li><a>Операция NOT (НЕ)</a></li>
13 <li><a>Операция NOT (НЕ)</a></li>
14 <li><a>Побитовые сдвиги</a></li>
14 <li><a>Побитовые сдвиги</a></li>
15 <li><a>Самое главное</a></li>
15 <li><a>Самое главное</a></li>
16 <li><a>Таблица ASCII</a></li>
16 <li><a>Таблица ASCII</a></li>
17 </ul><p>Побитовый оператор XOR обозначается знаком ^. Результат этой операции истинен, когда только один из битов равняется единице. Вот так это выглядит в таблице истинности:</p>
17 </ul><p>Побитовый оператор XOR обозначается знаком ^. Результат этой операции истинен, когда только один из битов равняется единице. Вот так это выглядит в таблице истинности:</p>
18 <p>Операция XOR широко применяется в криптографии при шифровании данных. Для этого нужен специальный ключ, с помощью которого информацию можно будет закодировать.</p>
18 <p>Операция XOR широко применяется в криптографии при шифровании данных. Для этого нужен специальный ключ, с помощью которого информацию можно будет закодировать.</p>
19 <p>Давайте зашифруем слово hello ключом ABC. Для этого переведём каждый символ по <a>таблице ASCII</a>в двоичную систему счисления. У нас получится следующее:</p>
19 <p>Давайте зашифруем слово hello ключом ABC. Для этого переведём каждый символ по <a>таблице ASCII</a>в двоичную систему счисления. У нас получится следующее:</p>
20 <ul><li>h = 1101000;</li>
20 <ul><li>h = 1101000;</li>
21 <li>e = 1100101;</li>
21 <li>e = 1100101;</li>
22 <li>l = 1101100;</li>
22 <li>l = 1101100;</li>
23 <li>o = 1101111;</li>
23 <li>o = 1101111;</li>
24 <li>A = 1000001;</li>
24 <li>A = 1000001;</li>
25 <li>B = 1000010;</li>
25 <li>B = 1000010;</li>
26 <li>C = 1000011.</li>
26 <li>C = 1000011.</li>
27 </ul><p>Теперь, используя оператор XOR, зашифруем каждый символ слова hello каждым последующим символом ключа. Такой алгоритм можно реализовать на любом языке программирования, мы сделали это на Java:</p>
27 </ul><p>Теперь, используя оператор XOR, зашифруем каждый символ слова hello каждым последующим символом ключа. Такой алгоритм можно реализовать на любом языке программирования, мы сделали это на Java:</p>
28 // Объявляем сообщение и ключ для кодирования String message = "hello"; String key = "ABC"; // Получаем массивы символов из строк char[] charsOfMessage = message.toCharArray(); char[] charsOfKey = key.toCharArray(); // Создаём переменную для хранения закодированного сообщения String encryptedString = ""; for (int i = 0; i &lt; charsOfMessage.length; i++) { // Выводим на экран каждую операцию System.out.println(charsOfMessage[i] + " ^ " + charsOfKey[i % key.length()] + " = " + (char) (charsOfMessage[i] ^ charsOfKey[i % key.length()])); // Кодируем каждый символ encryptedString += (char) (charsOfMessage[i] ^ charsOfKey[i % key.length()]); }<p>Если запустить код, то в терминале появятся символы<em>) ' / - -</em>. Именно так и выглядит зашифрованное слово hello:</p>
28 // Объявляем сообщение и ключ для кодирования String message = "hello"; String key = "ABC"; // Получаем массивы символов из строк char[] charsOfMessage = message.toCharArray(); char[] charsOfKey = key.toCharArray(); // Создаём переменную для хранения закодированного сообщения String encryptedString = ""; for (int i = 0; i &lt; charsOfMessage.length; i++) { // Выводим на экран каждую операцию System.out.println(charsOfMessage[i] + " ^ " + charsOfKey[i % key.length()] + " = " + (char) (charsOfMessage[i] ^ charsOfKey[i % key.length()])); // Кодируем каждый символ encryptedString += (char) (charsOfMessage[i] ^ charsOfKey[i % key.length()]); }<p>Если запустить код, то в терминале появятся символы<em>) ' / - -</em>. Именно так и выглядит зашифрованное слово hello:</p>
29 h ^ A = ) e ^ B = ' l ^ C = / l ^ A = - o ^ B = -<p>Алгоритм посимвольно кодирует слово hello каждым последующим символом ключа ABC, а под капотом компьютер переводит каждый символ в двоичную систему счисления и применяет оператор XOR:</p>
29 h ^ A = ) e ^ B = ' l ^ C = / l ^ A = - o ^ B = -<p>Алгоритм посимвольно кодирует слово hello каждым последующим символом ключа ABC, а под капотом компьютер переводит каждый символ в двоичную систему счисления и применяет оператор XOR:</p>
30 <em>Инфографика: Майя Мальгина для Skillbox Media</em><p>Для расшифровки получившегося значение нужно снова провести операцию XOR со строкой) ' / - - и нашим ключом:</p>
30 <em>Инфографика: Майя Мальгина для Skillbox Media</em><p>Для расшифровки получившегося значение нужно снова провести операцию XOR со строкой) ' / - - и нашим ключом:</p>
31 // Делим на символы зашифрованную строку char[] charsOfEncString = encryptedString.toCharArray(); for (int i = 0; i &lt; charsOfEncString.length; i++) { // Выводим в консоль текущую операцию System.out.println(charsOfEncString[i] + " ^ " + charsOfKey[i % key.length()] + " = " + (char) (charsOfEncString[i] ^ charsOfKey[i % key.length()])); // Кладём в переменную расшифрованный символ encryptedString += (char) (charsOfEncString[i] ^ charsOfKey[i % key.length()]); }<p>Как вы видите, мы снова получили исходное значение - hello:</p>
31 // Делим на символы зашифрованную строку char[] charsOfEncString = encryptedString.toCharArray(); for (int i = 0; i &lt; charsOfEncString.length; i++) { // Выводим в консоль текущую операцию System.out.println(charsOfEncString[i] + " ^ " + charsOfKey[i % key.length()] + " = " + (char) (charsOfEncString[i] ^ charsOfKey[i % key.length()])); // Кладём в переменную расшифрованный символ encryptedString += (char) (charsOfEncString[i] ^ charsOfKey[i % key.length()]); }<p>Как вы видите, мы снова получили исходное значение - hello:</p>
32 ) ^ A = h ' ^ B = e / ^ C = l - ^ A = l - ^ B = o<p>Побитовый оператор AND обозначается символом &amp;. AND делает то же, что и обычное умножение, поэтому в большинстве случаев в таблице истинности результат будет ложным:</p>
32 ) ^ A = h ' ^ B = e / ^ C = l - ^ A = l - ^ B = o<p>Побитовый оператор AND обозначается символом &amp;. AND делает то же, что и обычное умножение, поэтому в большинстве случаев в таблице истинности результат будет ложным:</p>
33 <p>Например, совершим логическое умножение букв R и Y. Для этого с помощью<a>таблицы ASCII</a>найдём двоичные значения букв и столбиком перемножим каждый бит:</p>
33 <p>Например, совершим логическое умножение букв R и Y. Для этого с помощью<a>таблицы ASCII</a>найдём двоичные значения букв и столбиком перемножим каждый бит:</p>
34 R<strong>B</strong>A &amp; B<strong>Y</strong>01010010<b><strong>R</strong></b>01011001<strong>R &amp; Y</strong>01010000<p>Мы получили двоичное число 01010000, которое по <a>таблице ASCII</a>равняется числу 80 и букве P. Логическое умножение также можно реализовать в виде кода, к примеру, на Java:</p>
34 R<strong>B</strong>A &amp; B<strong>Y</strong>01010010<b><strong>R</strong></b>01011001<strong>R &amp; Y</strong>01010000<p>Мы получили двоичное число 01010000, которое по <a>таблице ASCII</a>равняется числу 80 и букве P. Логическое умножение также можно реализовать в виде кода, к примеру, на Java:</p>
35 int r = 'R'; int y = 'Y'; System.out.println(Integer.toBinaryString(r)); System.out.println(Integer.toBinaryString(y)); System.out.println("_______"); System.out.println(Integer.toBinaryString(r &amp; y));<p>Метод Integer.toBinaryString() позволяет посмотреть, как тот или иной символ выглядит в двоичной системе счисления. Эти строки указаны лишь для примера, чтобы посмотреть, как работает операция AND. Скрипт будет правильно работать, даже если в нём будет только последняя строчка с логическим умножением:</p>
35 int r = 'R'; int y = 'Y'; System.out.println(Integer.toBinaryString(r)); System.out.println(Integer.toBinaryString(y)); System.out.println("_______"); System.out.println(Integer.toBinaryString(r &amp; y));<p>Метод Integer.toBinaryString() позволяет посмотреть, как тот или иной символ выглядит в двоичной системе счисления. Эти строки указаны лишь для примера, чтобы посмотреть, как работает операция AND. Скрипт будет правильно работать, даже если в нём будет только последняя строчка с логическим умножением:</p>
36 1010010 1011001 _______ 1010000<p>Побитовый оператор OR обозначается знаком |. Этот оператор работает как обычное арифметическое сложение. Единственное исключение в том, что отсутствуют разряды, то есть при сложении двух единиц всё равно получится единица (1 | 1 = 1):</p>
36 1010010 1011001 _______ 1010000<p>Побитовый оператор OR обозначается знаком |. Этот оператор работает как обычное арифметическое сложение. Единственное исключение в том, что отсутствуют разряды, то есть при сложении двух единиц всё равно получится единица (1 | 1 = 1):</p>
37 <p>Для примера напишем скрипт, который просчитает значения таблицы истинности и выведет её в консоль. В первой строчке объявим массив возможных комбинаций таблицы истинности, а далее в цикле проведём операцию OR с каждой парой значений:</p>
37 <p>Для примера напишем скрипт, который просчитает значения таблицы истинности и выведет её в консоль. В первой строчке объявим массив возможных комбинаций таблицы истинности, а далее в цикле проведём операцию OR с каждой парой значений:</p>
38 int[][] bits = new int [][]{{0,0}, {0,1}, {1,0}, {1,1}}; for (int i = 0, j = 0; i &lt; bits.length; i++) System.out.println(bits[i][j] + " | " + bits[i][j + 1] + " = " + (bits[i][j] | bits[i][j + 1]));<p>Если запустить код, то в консоли появится таблица истинности для операции OR:</p>
38 int[][] bits = new int [][]{{0,0}, {0,1}, {1,0}, {1,1}}; for (int i = 0, j = 0; i &lt; bits.length; i++) System.out.println(bits[i][j] + " | " + bits[i][j + 1] + " = " + (bits[i][j] | bits[i][j + 1]));<p>Если запустить код, то в консоли появится таблица истинности для операции OR:</p>
39 0 | 0 = 0 0 | 1 = 1 1 | 0 = 1 1 | 1 = 1<p>Побитовый оператор NOT обозначается знаком ~. NOT - унарный логический оператор, то есть применим только к одному биту. Операция инвертирует 0 в 1 и наоборот. Его ещё называют логическим отрицанием:</p>
39 0 | 0 = 0 0 | 1 = 1 1 | 0 = 1 1 | 1 = 1<p>Побитовый оператор NOT обозначается знаком ~. NOT - унарный логический оператор, то есть применим только к одному биту. Операция инвертирует 0 в 1 и наоборот. Его ещё называют логическим отрицанием:</p>
40 <p>Рассмотрим, как логическая операция NOT работает с цветами RGB-палитры. Каждый цвет в компьютере закодирован тремя числовыми значениями, которые мы можем перевести в двоичную систему счисления.</p>
40 <p>Рассмотрим, как логическая операция NOT работает с цветами RGB-палитры. Каждый цвет в компьютере закодирован тремя числовыми значениями, которые мы можем перевести в двоичную систему счисления.</p>
41 <p>Например, чёрный цвет в RGB-палитре записывается тремя нулям: (0, 0, 0), а в двоичной системе счисления это будет (00000000, 00000000, 00000000). Если инвертировать каждое значение оператором ~ (NOT), то у нас получится (11111111, 11111111, 11111111). В десятичной системе счисления это будет (255, 255, 255), а в RGB-палитре так записывается белый цвет:</p>
41 <p>Например, чёрный цвет в RGB-палитре записывается тремя нулям: (0, 0, 0), а в двоичной системе счисления это будет (00000000, 00000000, 00000000). Если инвертировать каждое значение оператором ~ (NOT), то у нас получится (11111111, 11111111, 11111111). В десятичной системе счисления это будет (255, 255, 255), а в RGB-палитре так записывается белый цвет:</p>
42 <em>Инфографика: Майя Мальгина для Skillbox Media</em><p>Операторы побитового сдвига обозначаются двумя знаками: &gt;&gt; (сдвиг битов вправо) и &lt;&lt; (сдвиг битов влево). С помощью этих операторов можно сдвинуть всю битовую цепочку влево или вправо.</p>
42 <em>Инфографика: Майя Мальгина для Skillbox Media</em><p>Операторы побитового сдвига обозначаются двумя знаками: &gt;&gt; (сдвиг битов вправо) и &lt;&lt; (сдвиг битов влево). С помощью этих операторов можно сдвинуть всю битовую цепочку влево или вправо.</p>
43 <p>Например, возьмём переменную X, равную 4, что в двоичном представлении будет 100:Если мы применим оператор побитового сдвига влево &lt;&lt;, то получим двоичное значение 1000, что в десятичном представлении будет равняться 8. Видно, что значение увеличится в два раза:</p>
43 <p>Например, возьмём переменную X, равную 4, что в двоичном представлении будет 100:Если мы применим оператор побитового сдвига влево &lt;&lt;, то получим двоичное значение 1000, что в десятичном представлении будет равняться 8. Видно, что значение увеличится в два раза:</p>
44 <p>Если мы применим сдвиг вправо &gt;&gt;, то значение уменьшится в два раза. К примеру, возьмём число 32:</p>
44 <p>Если мы применим сдвиг вправо &gt;&gt;, то значение уменьшится в два раза. К примеру, возьмём число 32:</p>
45 <p>Операциями побитового сдвига можно заменить деление и умножение на два. В реальных проектах надо внимательно применять эти операторы, так как в языках программирования они реализованы по-разному.</p>
45 <p>Операциями побитового сдвига можно заменить деление и умножение на два. В реальных проектах надо внимательно применять эти операторы, так как в языках программирования они реализованы по-разному.</p>
46 <p>В некоторых языках программирования, например Java, Kotlin, C# и JavaScript, есть оператор &gt;&gt;&gt; - беззнаковый сдвиг битов вправо. Дело в том, что в двоичном представлении чисел в этих языках, если первый бит равен нулю, значит, число положительное, а если единице - отрицательное. В таком случае обычная операция сдвига не трогает самый первый бит, оставляя число с тем же знаком. А операция беззнакового сдвига перемещает все биты:</p>
46 <p>В некоторых языках программирования, например Java, Kotlin, C# и JavaScript, есть оператор &gt;&gt;&gt; - беззнаковый сдвиг битов вправо. Дело в том, что в двоичном представлении чисел в этих языках, если первый бит равен нулю, значит, число положительное, а если единице - отрицательное. В таком случае обычная операция сдвига не трогает самый первый бит, оставляя число с тем же знаком. А операция беззнакового сдвига перемещает все биты:</p>
47 <em>Инфографика: Майя Мальгина для Skillbox Media</em><p>Сегодня вы узнали, какие существуют основные логические операции и как они работают. Кратко пройдёмся по каждому оператору:</p>
47 <em>Инфографика: Майя Мальгина для Skillbox Media</em><p>Сегодня вы узнали, какие существуют основные логические операции и как они работают. Кратко пройдёмся по каждому оператору:</p>
48 <ul><li><strong>AND (И)</strong> - обозначается знаком &amp; и умножает биты друг на друга. Значение истинно, когда оба бита равны единице.</li>
48 <ul><li><strong>AND (И)</strong> - обозначается знаком &amp; и умножает биты друг на друга. Значение истинно, когда оба бита равны единице.</li>
49 <li><strong>OR (ИЛИ)</strong> - обозначается знаком | и складывает два бита, не превышая разряда числа. Значение истинно, когда один или два бита равны единице.</li>
49 <li><strong>OR (ИЛИ)</strong> - обозначается знаком | и складывает два бита, не превышая разряда числа. Значение истинно, когда один или два бита равны единице.</li>
50 <li><strong>XOR (исключающее ИЛИ)</strong> - обозначается как |. Истина, если только один бит равен единице.</li>
50 <li><strong>XOR (исключающее ИЛИ)</strong> - обозначается как |. Истина, если только один бит равен единице.</li>
51 <li><strong>NOT</strong> - инвертирование бита. Единицу превращает в ноль и наоборот.</li>
51 <li><strong>NOT</strong> - инвертирование бита. Единицу превращает в ноль и наоборот.</li>
52 <li><strong>&gt;&gt;</strong> - побитовый сдвиг вправо. Сдвигает цепочку битов вправо. Применяясь в программировании, эта операция не изменяет положительность или отрицательность числа.</li>
52 <li><strong>&gt;&gt;</strong> - побитовый сдвиг вправо. Сдвигает цепочку битов вправо. Применяясь в программировании, эта операция не изменяет положительность или отрицательность числа.</li>
53 <li><strong>&lt;&lt;</strong> - побитовый сдвиг влево. Сдвигает биты влево, с конца добавляя ноль. Положительность или отрицательность также не изменяет.</li>
53 <li><strong>&lt;&lt;</strong> - побитовый сдвиг влево. Сдвигает биты влево, с конца добавляя ноль. Положительность или отрицательность также не изменяет.</li>
54 </ul><p><strong>ASCII</strong> - стандарт кодирования букв латинского алфавита, цифр, знаков препинания и специальных символов. В 1963 году Американская ассоциация стандартов приняла ASCII как основной способ представления текста в компьютере.</p>
54 </ul><p><strong>ASCII</strong> - стандарт кодирования букв латинского алфавита, цифр, знаков препинания и специальных символов. В 1963 году Американская ассоциация стандартов приняла ASCII как основной способ представления текста в компьютере.</p>
55 <em>Инфографика: Майя Мальгина для Skillbox Media</em><a><b>Бесплатный курс по Python ➞</b>Мини-курс для новичков и для опытных кодеров. 4 крутых проекта в портфолио, живое общение со спикером. Кликните и узнайте, чему можно научиться на курсе. Смотреть программу</a>
55 <em>Инфографика: Майя Мальгина для Skillbox Media</em><a><b>Бесплатный курс по Python ➞</b>Мини-курс для новичков и для опытных кодеров. 4 крутых проекта в портфолио, живое общение со спикером. Кликните и узнайте, чему можно научиться на курсе. Смотреть программу</a>