Операторы быстрого побитового и битового сдвига (с примерами)

В этом руководстве вы узнаете о различных побитовых операциях в Swift. Они используются для вычисления битового уровня в выражении.

Бит используется для обозначения двоичной цифры. Двоичная цифра может иметь два возможных значения: 0 или 1. Как программист начального уровня вам не нужно работать с операциями на уровне битов.

Достаточно работы с примитивными типами данных, такими как: integer, float, boolean, string и т. Д. Вам может потребоваться работать на битовом уровне, когда вы имеете дело с низкоуровневым программированием.

Swift предоставляет богатый набор операторов, помимо основных, для управления битами. Эти операторы похожи на логические операторы, за исключением того, что они работают с двоичными представлениями данных (битами).

Побитовые операторы - это операторы, которые используются для изменения отдельных битов операнда. Операнд - это переменная или константа, с которой выполняется операция.

Все побитовые операторы, доступные в Swift, перечислены ниже:

1. Побитовый оператор НЕ

Он представлен ~знаком тильды и может применяться к одному операнду. Это инвертирует все биты. т.е. меняет 1 на 0 и 0 на 1.

Если x - это переменная / константа, которая содержит двоичное значение, то есть 0 или 1. Побитовая операция not с переменной x может быть представлена ​​в таблице ниже:

НЕ
Икс ~ х
0 1
1 0

Пример 1: Побитовый оператор НЕ для целого числа без знака

 let initalNumber:UInt8 = 1 let invertedNumber = ~initalNumber print(invertedNumber) 

Когда вы запустите вышеуказанную программу, результат будет:

 254

В приведенной выше программе оператор let initalNumber:UInt8 = 1имеет тип Unsigned int размером 8 бит. Итак, 1 в десятичной системе счисления можно представить как 00000001двоичную.

Побитовый оператор not изменяет весь бит переменной или константы, бит 0 изменяется на 1, а бит 1 на 0. Таким образом, инвертированное число содержит биты 11111110. После преобразования в десятичное число оно представляется как 254. Таким образом, оператор print(invertedNumber)выводит на экран 254.

Вы также можете выполнять побитовый оператор непосредственно в битах как:

Пример 2: Побитовый оператор НЕ в битах

 let initialBits: UInt8 = 0b11111111 let invertedBits = ~initialBits print(invertedBits) 

Когда вы запустите вышеуказанную программу, результат будет:

 0

initialBits содержит двоичное значение 11111111, соответствующее 255 в десятичном формате . Для представления числа в двоичном формате у нас 0bесть префикс в литерале. Без 0bпрефикса он будет рассматривать его как обычное целое число, и вы получите ошибку переполнения (UInt8 может хранить числа только от 0 до 255).

Поскольку мы использовали побитовый оператор not, он меняет все 1 на 0. Таким образом, константа инвертированных битов содержит, 00000000что эквивалентно 0 в UInt8.

Пример 3: Побитовый оператор НЕ для целого числа со знаком

 let initalNumber:Int = 1 let invertedNumber = ~initalNumber print(invertedNumber) 

Когда вы запустите вышеуказанную программу, результат будет:

 -2

В приведенной выше программе 1 в десятичной системе счисления может быть представлена ​​как 00000001двоичная. Побитовый оператор not изменяет весь бит переменной или константы, бит 0 изменяется на 1, а бит 1 на 0. Таким образом, инвертированное число содержит биты 11111110. На экране должно появиться 254. Но вместо этого возвращает -2. Странно, правда ?? Давайте рассмотрим ниже, как это произошло.

let initalNumber:Int = 1представляет собой целое число со знаком, которое может содержать как положительные, так и отрицательные целые числа. Вот почему, когда мы применили оператор not для целого числа со знаком, возвращаемый двоичный файл также может представлять отрицательное число.

Как компилятор интерпретировал -2 как 11111110 двоичный?

Компилятор использовал дополнение Two для представления целых чисел. Чтобы получить два дополнительных отрицательных обозначения целого числа, вы должны сначала записать число в двоичном формате, затем инвертировать цифры и добавить единицу к результату.

Шаги, чтобы узнать двойное дополнение -2 :

  1. Запишите 2 в двоичной форме: 00000010
  2. Инвертируйте цифры. 0 становится 1, а 1 становится 0:11111101
  3. Добавить 1: 11111110

Вот так компилятор интерпретирует двоичное число 1111110как -2десятичное. Но есть небольшой поворот, который сделал компилятор, которого мы не заметили. Он также определил тип инвертированного числа как Int8тип.

Чтобы понять это, давайте посмотрим на пример ниже:

 print(Int8(bitPattern: 0b11111110)) print(0b11111110)

Когда вы запустите вышеуказанную программу, результат будет:

 -2 254

В приведенном выше примере компилятор обработал двоичное число до -2 в десятичном только для 8-разрядного целого числа со знаком. Поэтому оператор print(Int8(bitPattern: 0b11111110))выводит на экран -2.

Но для обычного целочисленного типа, размер которого составляет 32/64 бита и может содержать большие значения, он интерпретирует значение как 254. Следовательно, инструкция print(0b11111110)выводит на экран 254 .

2. Побитовый оператор И

Он представлен &двумя операндами и может применяться к ним. Оператор AND сравнивает два бита и возвращает 1, если оба бита равны 1, в противном случае возвращает 0.

Если x и y являются переменными / константами, которые содержат двоичное значение, то есть 0 или 1. Побитовая операция AND для x и y может быть представлена ​​в таблице ниже:

И
Икс у х и у
0 0 0
0 1 0
1 1 1
1 0 0

Пример 5: Побитовая операция И

 let xBits = 0b10000011 let yBits = 0b11111111 let result = xBits & yBits print("Binary:",String(result, radix: 2)) print(result)

Когда вы запустите вышеуказанную программу, результат будет:

 Двоичный: 10000011 131 

В приведенной выше программе оператор let result = xBits & yBitsобъединяет биты двух операндов xBits и yBits. Он возвращает 1, если оба бита равны 1, в противном случае возвращает 0.

String(value , radix: )инициализатор используется для представления числа в другой системе счисления. Если мы введем значение системы счисления 2. Он преобразует число в двоичную систему счисления. Точно так же мы можем использовать 16 для шестнадцатеричного и 10 для десятичного.

Оператор print("Binary:",String(result, radix: 2))выводит на экран Binary: 10000011 . 10000011эквивалентен 131 в десятичной системе, оператор print(result)выводит 131 в консоли.

3. Побитовый оператор ИЛИ

Он представлен как |и может применяться к двум операндам. Оператор побитового ИЛИ сравнивает два бита и генерирует результат 1, если один или несколько его входов равны 1, в противном случае - 0.

Если x и y являются переменными / константами, которые содержат двоичное значение, то есть 0 или 1. Операция побитового ИЛИ для x и y может быть представлена ​​в таблице ниже:

ИЛИ
Икс у х | у
0 0 0
0 1 1
1 1 1
1 0 1

Пример 6: Побитовая операция ИЛИ

 let xBits = 0b10000011 let yBits = 0b11111111 let result = xBits | yBits print("Binary:", String(result, radix: 2)) print(result) 

Когда вы запустите вышеуказанную программу, результат будет:

 Двоичный: 11111111 255 

В приведенной выше программе оператор let result = xBits | yBitsобъединяет биты двух констант xBits и yBits. Он возвращает 1, если какой-либо из битов равен 1, иначе он возвращает 0.

Оператор print("Binary:",String(result, radix: 2))выводит на экран Binary: 11111111 . Поскольку, 11111111эквивалентно 255десятичной системе, оператор print(result)выводит 255 на экране.

4. Побитовый оператор XOR.

Он представлен как ^и может применяться к двум операндам. Оператор XOR сравнивает два бита и генерирует результат 1, если ровно один из его входов равен 1, в противном случае он возвращает 0.

Если x и y являются переменными / константами, которые содержат двоичное значение, то есть 0 или 1. Побитовая операция XOR для x и y может быть представлена ​​в таблице ниже:

XOR
Икс у х у
0 0 0
0 1 1
1 1 0
1 0 1

Пример 7: Побитовая операция XOR

 let xBits = 0b10000011 let yBits = 0b11111111 let result = xBits yBits print("Binary:", String(result, radix: 2)) print(result) 

Когда вы запустите вышеуказанную программу, результат будет:

 Двоичный: 1111100 124 

В приведенной выше программе оператор let result = xBits yBitsобъединяет биты двух констант xBits и yBits. Он возвращает 1, если ровно один из битов равен 1, иначе он возвращает 0.

Оператор print("Binary:",String(result, radix: 2))выводит на экран Binary: 1111100 (эквивалент 01111100). Поскольку, 1111100эквивалентно 124десятичной системе, на экране print(result)выводится 124 .

5. Оператор побитового сдвига

Эти операторы используются для перемещения всех битов числа влево или вправо на определенное количество разрядов и могут применяться к одному операнду. Он представлен как <<или >>.

Есть два типа операторов сдвига:

Оператор побитового сдвига влево

  • Обозначается как <<
  • Это заставляет биты сдвигаться влево, указанное числом, за которым следует <<.
  • Позиции битов, которые были освобождены операцией сдвига, заполняются нулями.
  • Сдвиг целого числа влево на одну позицию увеличивает его значение вдвое.

Пример 8: Побитовый оператор сдвига влево

 let someBits:UInt8 = 0b11000100 print(someBits << 1) 

Когда вы запустите вышеуказанную программу, результат будет:

 136

В приведенной выше программе мы использовали оператор сдвига влево. Использование <<1 означает сдвиг бита на 1 влево. Цифры сдвигаются влево на одну позицию, а последняя цифра справа заполняется нулем.

Вы также можете видеть, что цифра, которая сдвинута "с конца" слева, потеряна. Он не повторяется снова справа. Сдвиг его на один бит влево удаляет 1 из двоичного файла и добавляет 0 справа, чтобы заполнить смещенное значение, а остальные другие биты смещаются влево на 1.

Это возвращает, 10001000что эквивалентно 136in UInt8. Следовательно, print(someBits << 1)оператор выводит 136 на экран.

Оператор побитового сдвига вправо

  • Обозначается как >>
  • Это заставляет биты сдвигаться вправо на число, за которым следует >>
  • Для чисел без знака битовые позиции, которые были освобождены операцией сдвига, заполняются нулями.
  • Для чисел со знаком (числа, которые также могут быть отрицательными) знаковый бит используется для заполнения освобожденных битовых позиций. Другими словами, если число положительное, используется 0, а если число отрицательное, используется 1.
  • Сдвиг вправо на одну позицию уменьшает его значение вдвое.

Пример 9: Оператор побитового сдвига вправо для целого числа без знака

 let someBits: UInt8 = 4 print(someBits>> 1) 

Когда вы запустите вышеуказанную программу, результат будет:

 2

В приведенной выше программе мы использовали оператор сдвига вправо для целого числа без знака. Использование >>1 означает сдвиг бит на 1 вправо. Позиции битов, которые были освобождены операцией сдвига, всегда заполняются нулями для целого числа без знака.

Поскольку 4 представляется как 00000100в двоичном формате. Сдвигая его на один бит вправо, возвращает 00000010результат, эквивалентный 2in UInt8. Таким образом, print(someBits>> 1)оператор выводит на экран 2.

Пример 10: Побитовый оператор сдвига вправо для целого числа со знаком

 let someBits:Int = -4 print(someBits>> 1) 

Когда вы запустите вышеуказанную программу, результат будет:

 -2

В приведенной выше программе мы использовали оператор сдвига вправо для целого числа без знака. В отличие от положительных чисел, использующихся >>для отрицательных чисел, вместо 0 используется 1 для заполнения пустого места.

Поскольку, -4представляется как 11111100в двоичном формате. Сдвигая его на один бит вправо и помещая 1 в свободную позицию, возвращает 11111110результат, эквивалентный -2для Int8типа. Таким образом, print(someBits>> 1)оператор выводит на экран -2.

Интересные статьи...