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. 按位移位运算符

此操作符用于将数字中的所有位移动到某个位置的左侧或右侧,并可应用于单个操作数,它表示为<<或>>。

有两种移位操作符:

按位左移位运算符

  • 表示为< <
  • 它使位元被移动到左边,由<<后面的数字指定。
  • 移位操作空出的位位置为零。
  • 将整数的位向左移动一个位置将使其值加倍

例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。

微信公众号
手机浏览(小程序)
0
分享到:
没有账号? 忘记密码?