W tym samouczku poznasz różne operacje bitowe w języku Swift. Są one używane do obliczeń na poziomie bitowym w wyrażeniu.
Bit jest używany do oznaczenia cyfry binarnej. Cyfra binarna może mieć dwie możliwe wartości, 0 lub 1. Jako początkujący programista nie musisz pracować z operacjami na poziomie bitów.
Wystarczy praca z prymitywnymi typami danych, takimi jak: integer, float, boolean, string itp. Być może będziesz musiał pracować na poziomie bitowym, gdy masz do czynienia z programowaniem niskiego poziomu.
Swift zapewnia bogaty zestaw operatorów, oprócz operatorów podstawowych, do manipulowania bitami. Operatory te są podobne do operatorów logicznych, z tą różnicą, że działają na binarnych reprezentacjach danych (bitach).
Operatory bitowe to operatory używane do zmiany pojedynczych bitów operandu. Operand to zmienna lub stała, w której wykonywana jest operacja.
Wszystkie operatory bitowe dostępne w swift są wymienione poniżej:
1. Operator bitowy NOT
Jest reprezentowany przez ~
znak tyldy i można go zastosować na pojedynczym operandzie. To odwraca wszystkie bity. tzn. zmienia się z 1 na 0 i 0 na 1.
Jeśli x jest zmienną / stałą, która przechowuje wartość binarną, tj. 0 lub 1. Brak operacji bitowej na zmiennej x można przedstawić w tabeli poniżej:
NIEx | ~ x |
---|---|
0 | 1 |
1 | 0 |
Przykład 1: operator bitowy NOT dla liczby całkowitej bez znaku
let initalNumber:UInt8 = 1 let invertedNumber = ~initalNumber print(invertedNumber)
Po uruchomieniu powyższego programu wynik będzie:
254
W powyższym programie instrukcja let initalNumber:UInt8 = 1
jest typu Unsigned int o rozmiarze 8 bitów. Tak więc 1 w systemie dziesiętnym można przedstawić 00000001
w postaci binarnej.
Operator bitowy not zmienia cały bit zmiennej lub stałej, bit 0 jest zmieniany na 1, a 1 na 0. Zatem invertedNumber zawiera bity 11111110
. Po przeliczeniu na dziesiętne jest reprezentowane jako 254. Tak więc instrukcja print(invertedNumber)
wyświetla na ekranie 254.
Możesz również wykonać operator bitowy bezpośrednio w bitach jako:
Przykład 2: operator bitowy NOT w bitach
let initialBits: UInt8 = 0b11111111 let invertedBits = ~initialBits print(invertedBits)
Po uruchomieniu powyższego programu wynik będzie:
0
initialBits zawiera wartość binarną 11111111
odpowiadającą 255 dziesiętnie. Aby przedstawić liczbę w systemie binarnym, mamy 0b
przedrostek w dosłownym. Bez 0b
prefiksu potraktuje to jako normalną liczbę całkowitą, a otrzymasz błąd przepełnienia (UInt8 może przechowywać liczby tylko od 0 do 255).
Ponieważ użyliśmy operatora bitowego not, zmienia on wszystkie 1 na 0. Tak więc stała invertedBits zawiera, 00000000
co jest równoważne 0 in UInt8
.
Przykład 3: operator bitowy NOT dla liczby całkowitej ze znakiem
let initalNumber:Int = 1 let invertedNumber = ~initalNumber print(invertedNumber)
Po uruchomieniu powyższego programu wynik będzie:
-2
W powyższym programie 1 w systemie dziesiętnym można przedstawić 00000001
w postaci binarnej. Operator bitowy not zmienia cały bit zmiennej lub stałej, bit 0 jest zmieniany na 1, a 1 na 0. Zatem invertedNumber zawiera bity 11111110
. Powinno to spowodować wyświetlenie 254 na ekranie. Ale zamiast tego zwraca -2. Dziwne, prawda? Przyjrzyjmy się poniżej, jak to się stało.
let initalNumber:Int = 1
jest liczbą całkowitą ze znakiem, która może zawierać zarówno dodatnie, jak i ujemne liczby całkowite. Dlatego jeśli zastosowaliśmy operator not dla liczby całkowitej ze znakiem, zwrócona wartość binarna może również reprezentować liczbę ujemną.
Jak kompilator zinterpretował wartość -2 jako 11111110
binarną?
Kompilator użył dopełnienia Two do reprezentowania liczb całkowitych. Aby uzyskać ujemną notację liczby całkowitej z dopełnieniem do dwóch, należy najpierw zapisać liczbę w systemie binarnym, a następnie odwrócić cyfry i dodać jedną do wyniku.
Kroki, aby dowiedzieć się, jak dopełnia się do -2 :
- Wpisz 2 w postaci binarnej:
00000010
- Odwróć cyfry. 0 staje się 1, a 1 staje się 0:
11111101
- Dodaj 1:
11111110
W ten sposób kompilator interpretuje liczbę binarną 1111110
jako -2
dziesiętną. Ale jest mały zwrot, który zrobił ten kompilator, którego nie zauważyliśmy. Wywnioskował również typ invertedNumber jako Int8
typ.
Aby to zrozumieć, zobaczmy przykład poniżej:
print(Int8(bitPattern: 0b11111110)) print(0b11111110)
Po uruchomieniu powyższego programu wynik będzie:
-2 254,
W powyższym przykładzie kompilator potraktował liczbę binarną do -2 w postaci dziesiętnej tylko dla 8-bitowej liczby całkowitej ze znakiem. Dlatego instrukcja print(Int8(bitPattern: 0b11111110))
wyświetla na ekranie -2.
Ale dla normalnego typu liczby całkowitej, którego rozmiar jest 32/64 bitowy i może przechowywać duże wartości, interpretuje wartość jako 254
. Dlatego instrukcja print(0b11111110)
wyświetla 254 na ekranie.
2. Operator bitowy AND
Jest reprezentowany przez &
i może być zastosowany na dwóch operandach. Operator AND porównuje dwa bity i zwraca 1, jeśli oba bity mają wartość 1, w przeciwnym razie zwraca 0.
Jeśli x i y są zmiennymi / stałymi, które przechowują wartość binarną, tj. 0 lub 1. Operację bitową AND na xiy można przedstawić w tabeli poniżej:
Ix | y | x & y |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
1 | 1 | 1 |
1 | 0 | 0 |
Przykład 5: operacja bitowa AND
let xBits = 0b10000011 let yBits = 0b11111111 let result = xBits & yBits print("Binary:",String(result, radix: 2)) print(result)
Po uruchomieniu powyższego programu wynik będzie:
Binarny: 10000011 131
W powyższym programie instrukcja let result = xBits & yBits
łączy bity dwóch operandów xBits i yBits. Zwraca 1, jeśli oba bity mają wartość 1, w przeciwnym razie zwraca 0.
String(value , radix: )
inicjator służy do reprezentowania liczby w innym systemie liczbowym. Jeśli podamy wartość podstawy 2. Przekształca liczbę w binarny system liczbowy. Podobnie możemy użyć 16 dla wartości szesnastkowych i 10 dla liczb dziesiętnych.
Instrukcja print("Binary:",String(result, radix: 2))
wyświetla na ekranie Binary: 10000011 . 10000011
jest odpowiednikiem liczby dziesiętnej 131, instrukcja print(result)
wyświetla wartość 131 w konsoli.
3. Operator bitowy OR
Jest reprezentowany jako |
i może być zastosowany na dwóch operandach. Operator bitowy OR porównuje dwa bity i generuje wynik 1, jeśli jedno lub więcej jego danych wejściowych ma wartość 1, w przeciwnym razie 0.
Jeśli x i y są zmiennymi / stałymi, które przechowują wartość binarną, tj. 0 lub 1. Operację bitową OR na x i y można przedstawić w tabeli poniżej:
LUBx | y | x | y |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 1 | 1 |
1 | 0 | 1 |
Przykład 6: operacja bitowa OR
let xBits = 0b10000011 let yBits = 0b11111111 let result = xBits | yBits print("Binary:", String(result, radix: 2)) print(result)
Po uruchomieniu powyższego programu wynik będzie:
Binarny: 11111111 255
W powyższym programie instrukcja let result = xBits | yBits
łączy bity dwóch stałych xBits i yBits. Zwraca 1, jeśli którykolwiek z bitów ma wartość 1, w przeciwnym razie zwraca 0.
Instrukcja print("Binary:",String(result, radix: 2))
wyświetla na ekranie Binary: 11111111 . Ponieważ, 11111111
jest odpowiednikiem 255
dziesiętnym, instrukcja print(result)
wyświetla na ekranie 255 .
4. Bitowy operator XOR
Jest reprezentowany jako ^
i może być zastosowany na dwóch operandach. Operator XOR porównuje dwa bity i generuje wynik 1, jeśli dokładnie jedno z jego danych wejściowych ma wartość 1, w przeciwnym razie zwraca 0.
Jeśli x i y są zmiennymi / stałymi, które przechowują wartość binarną, tj. 0 lub 1. Operację bitowego XOR na xiy można przedstawić w tabeli poniżej:
XORx | y | x y |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 1 | 0 |
1 | 0 | 1 |
Przykład 7: operacja Bitwise XOR
let xBits = 0b10000011 let yBits = 0b11111111 let result = xBits yBits print("Binary:", String(result, radix: 2)) print(result)
Po uruchomieniu powyższego programu wynik będzie:
Binarny: 1111100 124
W powyższym programie instrukcja let result = xBits yBits
łączy bity dwóch stałych xBits i yBits. Zwraca 1, jeśli dokładnie jeden z bitów ma wartość 1, w przeciwnym razie zwraca 0.
Instrukcja print("Binary:",String(result, radix: 2))
wyświetla na ekranie Binary: 1111100 (odpowiednik 01111100). Ponieważ, 1111100
jest odpowiednikiem 124
dziesiętnym, instrukcja print(result)
wyświetla 124 na ekranie.
5. Operator przesunięcia bitowego
Operatory te są używane do przenoszenia wszystkich bitów w liczbie w lewo lub w prawo o określoną liczbę miejsc i mogą być stosowane do pojedynczego operandu. Jest reprezentowany jako <<
lub >>
.
Istnieją dwa rodzaje operatorów zmianowych:
Operator przesunięcia bitowego w lewo
- Oznaczony jako
<<
- Powoduje to przesunięcie bitów w lewo, określonego przez liczbę, po której następuje
<<
. - Pozycje bitów, które zostały zwolnione przez operację przesunięcia, są wypełnione zerami.
- Przesunięcie bitów liczby całkowitej w lewo o jedną pozycję podwaja jej wartość
Przykład 8: Bitowy operator przesunięcia w lewo
let someBits:UInt8 = 0b11000100 print(someBits << 1)
Po uruchomieniu powyższego programu wynik będzie:
136
W powyższym programie użyliśmy operatora przesunięcia w lewo. Użycie <<
1 oznacza przesunięcie bitu o 1 w lewo. Cyfry zostaną przesunięte w lewo o jedną pozycję, a ostatnia cyfra po prawej stronie zostanie wypełniona zerem.
Możesz również zobaczyć, że cyfra przesunięta „z końca” z lewej strony została utracona. Nie zawija się ponownie z prawej strony. Przesunięcie go o jeden bit w lewo usuwa 1 z binarnego i dodaje 0 po prawej, aby wypełnić przesuniętą wartość, a także pozostałe bity są przesunięte w lewo o 1.
Zwraca 10001000
to, co jest równoważne z 136
in UInt8
. Dlatego print(someBits << 1)
instrukcja wyświetla 136 na ekranie.
Operator przesunięcia bitowego w prawo
- Oznaczony jako
>>
- Powoduje, że bity są przesuwane w prawo o liczbę, po której następuje
>>
- W przypadku liczb bez znaku pozycje bitów, które zostały zwolnione przez operację przesunięcia, są wypełnione zerami.
- W przypadku liczb ze znakiem (liczby, które mogą być również ujemne), bit znaku jest używany do wypełnienia zwolnionych pozycji bitów. Innymi słowy, jeśli liczba jest dodatnia, używane jest 0, a jeśli liczba jest ujemna, używane jest 1.
- Przesunięcie go w prawo o jedną pozycję zmniejsza o połowę jego wartość.
Przykład 9: Bitowy operator przesunięcia w prawo dla liczby całkowitej bez znaku
let someBits: UInt8 = 4 print(someBits>> 1)
Po uruchomieniu powyższego programu wynik będzie:
2
W powyższym programie użyliśmy operatora przesunięcia w prawo na liczbie całkowitej bez znaku. Użycie >>
1 oznacza przesunięcie bitu o 1 w prawo. Pozycje bitów, które zostały zwolnione przez operację przesunięcia, są zawsze wypełnione zerami na liczbie całkowitej bez znaku.
Ponieważ 4 jest reprezentowane jako 00000100
binarne. Przesunięcie go o jeden kawałek w prawo powoduje zwrócenie, 00000010
co odpowiada 2
in UInt8
. Dlatego print(someBits>> 1)
instrukcja wyświetla 2 na ekranie.
Przykład 10: operator przesunięcia bitowego w prawo dla liczby całkowitej ze znakiem
let someBits:Int = -4 print(someBits>> 1)
Po uruchomieniu powyższego programu wynik będzie:
-2
W powyższym programie użyliśmy operatora przesunięcia w prawo na liczbie całkowitej bez znaku. W przeciwieństwie do liczb dodatnich w przypadku liczb >>
ujemnych do wypełnienia pustego miejsca służy 1 zamiast 0.
Ponieważ, -4
jest reprezentowany jako 11111100
binarny. Przesunięcie go o jeden bit w prawo i umieszczenie 1 w wolnej pozycji zwraca wartość 11111110
odpowiadającą -2
for Int8
type. Dlatego print(someBits>> 1)
instrukcja wyświetla na ekranie wartość -2.