В този урок ще научите за различни битови операции в Swift. Те се използват за изчисляване на битово ниво в израз.
Бит се използва за означаване на двоична цифра. Двоична цифра може да има две възможни стойности или 0, или 1. Като програмист на ниво начинаещи, не е нужно да работите с операции на битово ниво.
Достатъчна е работата с примитивни типове данни като: цяло число, плувка, булево, низ и т.н. Може да се наложи да работите на битово ниво, когато се занимавате с програмиране на ниско ниво.
Swift предоставя богат набор от оператори, освен основните оператори, за манипулиране на битове. Тези оператори са подобни на логическите оператори, с изключение на това, че работят върху двоично представяне на данни (битове).
Побитовите оператори са оператори, които се използват за промяна на отделни битове на операнд. Операндът е променлива или константа, в която се извършва операцията.
Всички битови оператори, налични в swift, са изброени по-долу:
1. Побитов НЕ Оператор
Представен е със ~
знак тилда и може да се приложи върху един операнд. Това обръща всички битове. т.е. променя 1 на 0 и 0 на 1.
Ако x е променлива / константа, която съдържа двоична стойност, т.е. 0 или 1. Побитовата не операция върху x променливата може да бъде представена в таблицата по-долу:
НЕх | ~ х |
---|---|
0 | 1 |
1 | 0 |
Пример 1: Побитов оператор NOT за неподписано цяло число
let initalNumber:UInt8 = 1 let invertedNumber = ~initalNumber print(invertedNumber)
Когато стартирате горната програма, изходът ще бъде:
254
В горната програма операторът let initalNumber:UInt8 = 1
е от тип Unsigned int с размер 8 бита. И така, 1 в десетичен знак може да бъде представен като 00000001
в двоичен.
Побитовият оператор not променя всички битове на променлива или константа, битът 0 се променя на 1 и 1 на 0. Така че invertedNumber съдържа битове 11111110
. След преобразуването му в десетично число се представя като 254. И така, изявлението print(invertedNumber)
извежда 254 на екрана.
Можете също да изпълнявате битови оператори директно в битовете като:
Пример 2: Побитов оператор NOT в битове
let initialBits: UInt8 = 0b11111111 let invertedBits = ~initialBits print(invertedBits)
Когато стартирате горната програма, изходът ще бъде:
0
InitialBits съдържа двоична стойност, 11111111
която съответства на 255 в десетични знаци. За да представим числото в двоичен файл, имаме 0b
като префикс в литерала. Без 0b
като префикс, той ще го третира като нормално цяло число и ще получите грешка при препълване (UInt8 може да съхранява числа само от 0 до 255).
Тъй като сме използвали побитовия оператор not, той променя всички 1 на 0. И така, константата invertedBits съдържа, 00000000
което е еквивалентно на 0 in UInt8
.
Пример 3: Побитов оператор NOT за подписано цяло число
let initalNumber:Int = 1 let invertedNumber = ~initalNumber print(invertedNumber)
Когато стартирате горната програма, изходът ще бъде:
-2
В горната програма 1 в десетичен знак може да бъде представен като 00000001
в двоичен. Побитовият оператор not променя целия бит на променлива или константа, битът 0 се променя на 1 и 1 на 0. И така, invertedNumber съдържа битове 11111110
. Това трябва да изведе 254 на екрана. Но вместо това връща -2. Странно, нали ?? Нека разгледаме по-долу как се случи това.
let initalNumber:Int = 1
е подписан int, който може да съдържа както положителни, така и отрицателни цели числа. Ето защо, когато приложихме не оператор за подписано цяло число, върнатият двоичен файл също може да представлява отрицателно число.
Как компилаторът интерпретира -2 като 11111110
в двоичен файл?
Компилаторът използва допълнението Two, за да представи цели числа. За да получите отрицателната нотация на двете числа на цяло число, първо трябва да запишете числото в двоичен файл, след това да обърнете цифрите и да добавите едно към резултата.
Стъпки, за да разберете допълнението на Two от -2 :
- Напишете 2 в двоична форма:
00000010
- Обърнете цифрите. 0 става 1 и 1 става 0:
11111101
- Добавете 1:
11111110
Ето как компилаторът интерпретира двоичното число 1111110
като -2
десетично. Но има малко обрат, направен от компилатора, който не забелязахме. Той също така изведе типа invertedNumber като Int8
тип.
За да разберем това, нека видим пример по-долу:
print(Int8(bitPattern: 0b11111110)) print(0b11111110)
Когато стартирате горната програма, изходът ще бъде:
-2 254
В горния пример компилаторът третира двоичното число до -2 в десетичен знак само за Signed 8-Bit Integer. Следователно изразът print(Int8(bitPattern: 0b11111110))
извежда -2 на екрана.
Но за нормалния тип цяло число, чийто размер е 32/64 бита и може да съдържа големи стойности, той интерпретира стойността като 254
. Следователно изразът print(0b11111110)
извежда 254 на екрана.
2. Побитово И Оператор
Той е представен от &
и може да се приложи върху два операнда. Операторът AND сравнява два бита и връща 1, ако двата бита са 1, в противен случай връща 0.
Ако x и y са променлива / константа, която съдържа двоична стойност, т.е. 0 или 1. Побитовата операция И върху x и y може да бъде представена в таблицата по-долу:
Их | у | 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: )
инициализаторът се използва за представяне на число в различна бройна система. Ако предоставим radix стойност 2. Той преобразува числото в двоична бройна система. По същия начин можем да използваме 16 за шестнадесетичен и 10 за десетични.
Извлечението print("Binary:",String(result, radix: 2))
извежда двоичен: 10000011 на екрана. 10000011
е еквивалентно на 131 в десетичен знак, изразът print(result)
извежда 131 в конзолата.
3. Побитови ИЛИ Оператор
Представен е като |
и може да се приложи върху два операнда. Побитовият оператор ИЛИ сравнява два бита и генерира резултат 1, ако един или повече от неговите входове са 1, иначе 0.
Ако x и y са променлива / константа, която съдържа двоична стойност, т.е. 0 или 1. Побитовата операция ИЛИ върху x и y може да бъде представена в таблицата по-долу:
ИЛИх | у | x | у |
---|---|---|
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))
извежда двоичен: 11111111 на екрана. Тъй като 11111111
е еквивалентно на 255
десетичната, изразът print(result)
извежда 255 на екрана.
4. Побитов XOR оператор
Представен е като ^
и може да се приложи върху два операнда. Операторът XOR сравнява два бита и генерира резултат 1, ако точно един от входовете му е 1, в противен случай връща 0.
Ако x и y са променлива / константа, която съдържа двоична стойност, т.е. 0 или 1. Побитовата XOR операция върху x и y може да бъде представена в таблицата по-долу:
XORх | у | x y |
---|---|---|
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))
извежда двоично: 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
В горната програма използвахме оператор за дясна смяна на неподписано цяло число. За разлика от положителните числа, използвайки >>
за отрицателни числа, 1 се използва, за да запълни свободното място, вместо 0.
Тъй като -4
е представен като 11111100
в двоичен файл. Преместването му с един бит надясно и поставянето на 1 на свободно място, връща, 11111110
което е еквивалентно на -2
за Int8
тип. Следователно print(someBits>> 1)
изразът извежда -2 на екрана.