在本教程中,您將學習 Swift 中的不同位操作。它們用于表達式中的位級計算。
位用來表示二進制數(shù)字。一個二進制數(shù)字可以有兩個可能的值0或1。作為一個初級程序員,您不必在位級別使用操作。
使用原始數(shù)據(jù)類型,例如:integer, float, boolean, string等就足夠了。在處理低級編程時,您可能需要在位級工作。
除了基本運算符外,Swift 還提供了一組豐富的操作符來操作位。這些運算符類似于邏輯運算符,只是它們處理數(shù)據(jù)(位)的二進制表示。
按位運算符是用于更改操作數(shù)的各個位的運算符。 操作數(shù)是在其中執(zhí)行運算的變量或常量。
以下列出了swift中可用的所有位運算符:
它由波浪符 ~ 表示,并可以應(yīng)用于單個操作數(shù)。 這會將所有位反轉(zhuǎn)。 即將1更改為0,將0更改為1。
如果x是一個保存二進制值(即0或1)的變量/常量,則x變量的按位非運算可以表示在下表中:
x | ~x |
---|---|
0 | 1 |
1 | 0 |
let initalNumber:UInt8 = 1 let invertedNumber = ~initalNumber print(invertedNumber)
當您運行上述程序時,輸出將是:
254
在上面的程序中,語句let initalNumber:UInt8 = 1 的類型為Unsigned int,大小為8位。因此,十進制的1可以表示為00000001二進制。
按位非運算符會更改變量或常量的所有位,位0會更改為1,而1會更改為0。因此,反向數(shù)字包含位11111110。將其轉(zhuǎn)換為十進制后,它表示為254。因此,語句 print(invertedNumber )在屏幕上輸出254。
也可以直接在位中執(zhí)行按位運算符,如下所示:
let initialBits: UInt8 = 0b11111111 let invertedBits = ~initialBits print(invertedBits)
當您運行上述程序時,輸出將是:
0
initialBits包含二進制值11111111,它對應(yīng)于十進制255。 為了用二進制表示數(shù)字,我們在文字中以0b作為前綴。 如果沒有0b作為前綴,它將把它當作普通整數(shù)對待,并且會出現(xiàn)溢出錯誤(UInt8只能存儲0到255之間的數(shù)字)。
由于我們使用了按位非運算符,因此將所有1都更改為0。因此,常量reverseBits包含00000000,這等效于UInt8中的0。
let initalNumber:Int = 1 let invertedNumber = ~initalNumber print(invertedNumber)
當您運行上述程序時,輸出將是:
-2
在上面的程序中,十進制的1可以二進制表示為00000001。 按位非運算符將更改變量或常量的所有位,將位0更改為1,將1更改為0。因此,反轉(zhuǎn)數(shù)字包含位11111110。這應(yīng)在屏幕中輸出254。 而是返回-2。 奇怪吧? 讓我們在下面看看這是如何發(fā)生的。
let initalNumber: Int = 1是一個有符號 Int,可以同時包含正整數(shù)和負整數(shù)。這就是為什么當我們對有符號整數(shù)應(yīng)用非運算符時,返回的二進制數(shù)也可能表示負數(shù)。
編譯器如何將 -2 解釋 為11111110 二進制形式?
編譯器使用二進制補碼表示整數(shù)。 要獲得整數(shù)的二進制補碼負號,您應(yīng)該首先以二進制形式寫出數(shù)字,然后將數(shù)字取反,然后在結(jié)果中加一個。
求-2的補碼的步驟:
以二進制形式寫2: 00000010
反轉(zhuǎn)數(shù)字。0變?yōu)?,而1變?yōu)?:11111101
加1: 11111110
這就是編譯器將二進制數(shù)1111110解釋為十進制中的-2的方式。 但是,編譯器有一個我們沒有注意到的小問題。 它還推斷 invertedNumber 的類型為Int8類型。
為了理解這一點,讓我們看下面的實例:
print(Int8(bitPattern: 0b11111110)) print(0b11111110)
當您運行上述程序時,輸出將是:
-2 254
在上面的示例中,編譯器僅對帶符號的8位整數(shù)將二進制數(shù)處理為十進制的-2。因此,語句print(Int8(bitPattern: 0b11111110))在屏幕上輸出-2。
但是對于大小為32/64位并且可以容納較大值的普通整數(shù)類型,它將值解釋為254。因此,語句在屏幕上print(0b11111110)輸出254。
它由 & 表示,可以應(yīng)用于兩個操作數(shù)。AND運算符比較兩個位,如果兩個位均為1,則返回1,否則返回0。
如果x和y是變量/常量,保存二進制值,即0或1。x和y上的位與運算可表示為下表:
x | y | x & y |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
1 | 1 | 1 |
1 | 0 | 0 |
let xBits = 0b10000011 let yBits = 0b11111111 let result = xBits & yBits print("Binary:",String(result, radix: 2)) print(result)
當您運行上述程序時,輸出將是:
Binary: 10000011 131
在上面的程序中,語句 let result=xBits&yBits 組合了兩個操作數(shù)xBits和yBits的位。 如果這兩個位都是1,則返回1,否則返回0。
String(value , radix: )初始值設(shè)定項用于表示不同數(shù)制中的數(shù)字。 如果我們提供基數(shù)值2。它將數(shù)字轉(zhuǎn)換為二進制數(shù)系統(tǒng)。 同樣,我們可以用16表示十六進制,用10表示十進制。
該語句print("Binary:",String(result, radix: 2))在屏幕上輸出 Binary:10000011。10000011等于十進制的131,語句print(result)在控制臺中輸出131。
它由 |表示,并且可以應(yīng)用于兩個操作數(shù)。如果按位或運算符的一個或多個輸入為1,則將兩個位相比較并生成結(jié)果1,否則為0。
如果x和y是保持二進制值(即0或1)的變量/常數(shù),則x和y的按位或運算可以表示為下表:
x | y | x | y |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 1 | 1 |
1 | 0 | 1 |
let xBits = 0b10000011 let yBits = 0b11111111 let result = xBits | yBits print("Binary:", String(result, radix: 2)) print(result)
當您運行上述程序時,輸出將是:
Binary: 11111111 255
在上面的程序中,let result = xBits | yBits 語句結(jié)合了兩個常量 xBits 和 yBits 的位。如果任何位都是1,則返回1,否則返回0。
該語句 print("Binary:",String(result, radix: 2)) 在屏幕上輸出Binary:11111111。由于11111111與255十進制等效,因此print(result)語句在屏幕上輸出255。
它由^表示,可以應(yīng)用于兩個操作數(shù)。異或運算符比較兩個位,如果只有一個輸入是1,則生成結(jié)果1,否則返回0。
如果x和y是變量/常量,保存二進制值,即0或1。x和y上的位異或運算可表示為下表:
x | y | x ^ y |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 1 | 0 |
1 | 0 | 1 |
let xBits = 0b10000011 let yBits = 0b11111111 let result = xBits ^ yBits print("Binary:", String(result, radix: 2)) print(result)
當您運行上述程序時,輸出將是:
Binary: 1111100 124
在上面的程序中,let result = xBits ^ yBits 語句結(jié)合了兩個常量 xBits 和 yBits 的位。如果其中一個位正好是1,則返回1,否則返回0。
該語句print("Binary:",String(result, radix: 2))在屏幕上輸出Binary:1111100(相當于01111100)。由于1111100等效124于十進制,因此語句print(result)在屏幕上輸出124。
該運算符用于將數(shù)字中的所有位向左或向右移動一定數(shù)量的位置,并且可以應(yīng)用于單個操作數(shù)。它表示為<<或>>。
移位運算符有兩種:
表示為 <<
它會導致位向左移位,該移位是由數(shù)字后跟 << 指定的。
移位操作空出的位位置用零填充。
將整數(shù)的位左移一個位置會使其值加倍
let someBits:UInt8 = 0b11000100 print(someBits << 1)
當您運行上述程序時,輸出將是:
136
在上面的程序中,我們使用了左移運算符。使用<<1表示將位向左移動1。這些數(shù)字向左移動一個位置,右側(cè)的最后一個數(shù)字填充零。
您還可以看到從左側(cè)“末端”移位的數(shù)字丟失。 它不會再次從右側(cè)繞回。 將其向左移位一位將從二進制中移除1,并在右側(cè)添加0以填充移位值,而其他位的其余位則向左位置移位1。
返回10001000,相當于UInt8中的136。因此,print(someBits<<1) 語句在屏幕中輸出136。
表示為 >>
它會導致位向右移位,移位的數(shù)字后跟 >>
對于無符號數(shù)字,移位操作騰出的位位置是零填充的。
對于帶符號的數(shù)字(也可以為負的數(shù)字),符號位用于填充騰出的位位置。換句話說,如果數(shù)字為正,則使用0;如果數(shù)字為負,則使用1。
向右移動一個位置,其值將減半。
let someBits: UInt8 = 4 print(someBits >> 1)
當您運行上述程序時,輸出將是:
2
在上面的程序中,我們對無符號整數(shù)使用了右移運算符。使用 >>1意味著將位向右移動1。移位操作騰出的位位置對于無符號整數(shù)總是零填充。
因為,4在二進制中表示為00000100。右移一位,返回00000010,相當于UInt8中的2。因此,print(someBits>>1) 語句在屏幕中輸出2。
let someBits:Int = -4 print(someBits >> 1)
當您運行上述程序時,輸出將是:
-2
在上面的程序中,我們對無符號整數(shù)使用了右移運算符。 與正數(shù)不同,使用>>表示負數(shù),使用1填充空位,而不是0。
因為,-4在二進制中表示為11111100。右移一位并將1置于空位,返回11111110,這相當于Int8類型的-2。因此,print(someBits>>1)語句在屏幕中輸出-2。