swift按位和移位操作符 – Swift最新教程

上一章Swift教程请查看:swift三元条件运算符(三目运算符)
在本教程中,你将了解Swift中不同的位操作,它们用于表达式中的位级计算。
位是用来表示二进制数字的,一个二进制数字可以有两个可能的值,0或1。作为一个初级程序员,你不必在位级别上处理操作。
处理原始数据类型,如:整数、浮点数、布尔值、字符串等就足够了,在处理底层编程时,你可能需要在位级别上工作。
除了基本操作符之外,Swift还提供了一组丰富的操作符来操作位,这些操作符与逻辑操作符类似,只是它们处理的是数据的二进制表示(位)。
按位运算符是用来改变操作数的个别位的运算符,操作数是执行操作的变量或常量。
swift提供的所有位操作符如下:
1. 按位取反或非运算符它由波浪~符号表示,可以应用于单个操作数,这是所有位的倒数或相反数,也就是从1到0,从0到1。
如果x是一个包含二进制值i的变量/常数,如0或1,对x变量的按位取反操作如下表所示:
NOT非运算符

x ~x
0 1
1 0
例1:无符号整数的按位非运算符
let initalNumber:UInt8 = 1 let invertedNumber = ~initalNumber print(invertedNumber)

在上面的程序中,语句let initalNumber:UInt8 = 1的类型是大小为8位的无符号整型,因此,1可以用二进制表示为00000001。
按位非运算符改变了一个变量或常数的所有位,0位变成了1,1变成了0。所以invertedNumber包含了11111110位。把它转换成小数后,它表示为254。因此,语句print(invertedNumber)在屏幕中输出254。
你也可以在多个位上直接执行按位运算符:
例2:按位非/取反操作符
let initialBits: UInt8 = 0b11111111 let invertedBits = ~initialBits print(invertedBits)

initialBits包含二进制值11111111,它对应于255的十进制数。为了表示二进制中的数字,我们在文字中以0b作为前缀。如果没有0b作为前缀,它将把它当作普通整数,你将得到一个溢出错误(UInt8只能存储0到255之间的数字)。
因为我们使用了按位不运算符,所以它把所有的1变成0,因此,常量invertedBits包含00000000,它在UInt8中等于0。
例3:带符号整数的按位非运算符
let initalNumber:Int = 1 let invertedNumber = ~initalNumber print(invertedNumber)

在上面的程序中,十进制的1可以表示为二进制的00000001。按位不运算符改变了一个变量或常数的所有位,0位变成了1,1变成了0。所以,invertedNumber包含了11111110位,这应该在屏幕中输出254,而不是返回-2。很奇怪,对吧???让我们来探索一下这是如何发生的。
let initalNumber:Int = 1是一个有符号的整数,可以同时保存正整数和负整数。这就是为什么当我们对一个带符号整数应用not运算符时,返回的二进制也可能表示一个负数。
编译器如何将-2解释为二进制的11111110 ?编译器用2的补码来表示整数,要得到整数的补数负号,你应该先把这个数写成二进制的形式,然后把数字反过来,再把1加到结果上。
求2的-2补码的步骤:
  • 把2写成二进制形式:00000010
  • 按位取反,0变成1,1变成0:11111101
  • 加1:11111110
这就是编译器将二进制数字1111110解释为-2的方式。但是,编译器做了一点小小的改变,我们没有注意到,它还将invertedNumber的类型推断为Int8类型。
为了理解这一点,让我们看看下面的例子:
print(Int8(bitPattern: 0b11111110)) print(0b11111110)

在上面的例子中,编译器只将带符号的8位整数的二进制数处理为-2。因此,语句print(Int8(bitPattern: 0b11111110))在屏幕上输出-2。
但是对于大小为32/64位并且可以容纳大值的普通整数类型,它将该值解释为254,因此,语句print(0b11111110)在屏幕上输出254。
2. 按位与操作符它由& 表示,可以应用于两个操作数,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
例5:按位与运算符
let xBits = 0b10000011 let yBits = 0b11111111 let result = xBits & yBits print("Binary:",String(result, radix: 2)) print(result)

在上面的程序中,let result = xBits & yBits语句组合了两个操作数xBits和yBits的位。它返回1它的两位都是1,否则它返回0。
初始化器用于表示不同数字系统中的数字,如果我们提供基数值2,它将数字转换成二进制数字系统。类似地,十六进制可以用16,十进制可以用10。
语句print(“ Binary:” ,String(result,基数:2))在屏幕上输出Binary: 10000011,10000011相当于十进制的131,语句print(result)在控制台中输出131。
3. 按位或运算符它表示为|,可以应用于两个操作数。按位或运算符比较两个位,如果一个或多个输入为1,则生成1的结果,否则为0。
如果x和y是变量/常数,其中包含二进制值,如0或1,x和y的按位或运算如下表所示:
按位或运算符
x y 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)

在上面的程序中,let result = xBits | yBits语句组合了两个常量xBits和yBits的位。如果任何一位是1,它返回1,否则返回0。
语句print(“ Binary:” ,String(result,基数:2))在屏幕上输出Binary: 11111111。由于11111111在小数点后等于255,因此语句print(result)在屏幕上输出255。
4. 按位异或运算符它表示为^,可以应用于两个操作数,XOR操作符比较两个位,如果其中一个输入恰好为1,则生成1的结果,否则返回0。
如果x和y是变量/常数,其中包含二进制值,如0或1,x和y的按位异或运算如下表所示:
按位异或运算
x y 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)

在上面的程序中,语句let result = xBits ^ yBits组合了两个常量xBits和yBits。如果其中一位正好是1,它就返回1,否则返回0。
语句print(“ Binary:” ,String(result,基数:2))在屏幕上输出Binary: 1111100(相当于01111100)。由于1111100等于124(以小数表示),因此语句print(result)在屏幕上输出124。
5. 按位移位运算符此操作符用于将数字中的所有位移动到某个位置的左侧或右侧,并可应用于单个操作数,它表示为< < 或> > 。
有两种移位操作符:
【swift按位和移位操作符 – Swift最新教程】按位左移位运算符
  • 表示为< <
  • 它使位元被移动到左边,由< < 后面的数字指定。
  • 移位操作空出的位位置为零。
  • 将整数的位向左移动一个位置将使其值加倍
例8:按位左移操作符
let someBits:UInt8 = 0b11000100 print(someBits < < 1)

在上面的程序中,我们使用了左移位运算符,使用< < 1表示将位向左移动1,数字向左移动了一个位置,右边的最后一个数字是0。
你也可以看到从左边移出“末端”的数字丢失了,它不再从右边环绕,将它向左移动1位将1从二进制中移除,并向右添加0来填充移动后的值,其他的位也向左移动1位。
返回10001000,相当于UInt8中的136。因此,print(someBits < < 1)语句在屏幕上输出136。
按位右移位运算符
  • 指示为> >
  • 它使位被> > 后面的数字向右移位
  • 对于无符号数字,移位操作空出的位位置是零填充的。
  • 对于有符号的数字(也可以是负数),符号位用于填充空出的位位置。换句话说,如果数字是正数,就用0,如果数字是负数,就用1。
  • 右移一个位置,值减半。
例9:无符号整数的按位右移运算符
let someBits: UInt8 = 4 print(someBits >> 1)

在上面的程序中,我们对一个无符号整数使用了右移位运算符。使用> > 1表示将位向右移动1。移位操作空出的位位置在无符号整数上始终为零。
因为,4在二进制中表示为00000100。向右移动一位,返回00000010,等于UInt8中的2。因此,在屏幕上打印(someBits > > 1)语句输出2。
例10:带符号整数的按位右移运算符
let someBits:Int = -4 print(someBits >> 1)

在上面的程序中,我们对一个无符号整数使用了右移位运算符。与正数不同,负数使用> > ,1被用来填补空缺,而不是0。
因为,-4在二进制中表示为11111100。将它向右移动一位并将1放置在空位置,返回11111110,这对于Int8类型来说相当于-2。因此,在屏幕上打印(someBits > > 1)语句输出-2。

    推荐阅读