В этом руководстве вы узнаете о различных побитовых операциях в 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 :
- Запишите 2 в двоичной форме:
00000010
- Инвертируйте цифры. 0 становится 1, а 1 становится 0:
11111101
- Добавить 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
что эквивалентно 136
in UInt8
. Следовательно, print(someBits << 1)
оператор выводит 136 на экран.
Оператор побитового сдвига вправо
- Обозначается как
>>
- Это заставляет биты сдвигаться вправо на число, за которым следует
>>
- Для чисел без знака битовые позиции, которые были освобождены операцией сдвига, заполняются нулями.
- Для чисел со знаком (числа, которые также могут быть отрицательными) знаковый бит используется для заполнения освобожденных битовых позиций. Другими словами, если число положительное, используется 0, а если число отрицательное, используется 1.
- Сдвиг вправо на одну позицию уменьшает его значение вдвое.
Пример 9: Оператор побитового сдвига вправо для целого числа без знака
let someBits: UInt8 = 4 print(someBits>> 1)
Когда вы запустите вышеуказанную программу, результат будет:
2
В приведенной выше программе мы использовали оператор сдвига вправо для целого числа без знака. Использование >>
1 означает сдвиг бит на 1 вправо. Позиции битов, которые были освобождены операцией сдвига, всегда заполняются нулями для целого числа без знака.
Поскольку 4 представляется как 00000100
в двоичном формате. Сдвигая его на один бит вправо, возвращает 00000010
результат, эквивалентный 2
in 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.