Swift 的位运算
# Swift 的位运算
提示
位运算符(Bitwise Operators): 将操作数 当作32位的比特序列(由0和1组成)(二进制)。按位操作符操作数字的二进制形式。
在许多古老的微处理器上, 位运算比加减运算略快, 通常位运算比乘除法运算要快很多。 在现代架构中, 情况并非如此:位运算的运算速度通常与加法运算相同(仍然快于乘法运算)。-- 维基百科
Swift 位运算与大部分语言运算一样。良好的位运算有助于开发效率提升。
# 位运算 常见的 符号
运算符 | 用法 | 描述 |
---|---|---|
按位与(AND) | a & b | 对于每一个比特位,只有两个操作数相应的比特位都是1时,结果才为1,否则为0。 |
按位或(OR) | a或b | 对于每一个比特位,当两个操作数相应的比特位至少有一个1时,结果为1,否则为0。 |
按位异或(XOR) | a ^ b | 对于每一个比特位,当两个操作数相应的比特位有且只有一个1时,结果为1,否则为0。 |
按位非(NOT) | ~ a | 反转操作数的比特位,即0变成1,1变成0。 |
左移(Left shift) | a << b | 将 a 的二进制形式向左移 b (< 32) 比特位,右边用0填充 |
有符号右移 | a >> b | 将 a 的二进制表示向右移 b (< 32) 位,丢弃被移出的位。 |
有符号右移 | a >>> b | 将 a 的二进制表示向右移 b (< 32) 位,丢弃被移出的位。 |
/// & (按位与)
9 (base 10) = 00000000000000000000000000001001 (base 2)
14 (base 10) = 00000000000000000000000000001110 (base 2)
--------------------------------
14 & 9 (base 10) = 00000000000000000000000000001000 (base 2) = 8 (base 10)
/// | (按位或)
9 (base 10) = 00000000000000000000000000001001 (base 2)
14 (base 10) = 00000000000000000000000000001110 (base 2)
--------------------------------
14 | 9 (base 10) = 00000000000000000000000000001111 (base 2) = 15 (base 10)
/// ^ (按位异或)
9 (base 10) = 00000000000000000000000000001001 (base 2)
14 (base 10) = 00000000000000000000000000001110 (base 2)
--------------------------------
14 ^ 9 (base 10) = 00000000000000000000000000000111 (base 2) = 7 (base 10)
/// ~ (按位非) 对任一数值 x 进行按位非操作的结果为 -(x + 1)。例如,~5 结果为 -6。
9 (base 10) = 00000000000000000000000000001001 (base 2)
--------------------------------
~9 (base 10) = 11111111111111111111111111110110 (base 2) = -10 (base 10)
/// << (左移)
/// 该操作符会将第一个操作数向左移动指定的位数。向左被移出的位被丢弃,右侧用 0 补充。
/// 在数字 x 上左移 y 比特得到 x * 2y.
9 (base 10): 00000000000000000000000000001001 (base 2)
--------------------------------
9 << 2 (base 10): 00000000000000000000000000100100 (base 2) = 36 (base 10)
/// >> (有符号右移)
/// 该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃,拷贝最左侧的位以填充左侧。由于新的最左侧的位总是和以前相同,符号位没有被改变。所以被称作“符号传播”
/// 9 >> 2 得到 2:
9 (base 10): 00000000000000000000000000001001 (base 2)
--------------------------------
9 >> 2 (base 10): 00000000000000000000000000000010 (base 2) = 2 (base 10)
/// -9 >> 2 得到 -3,因为符号被保留了。
-9 (base 10): 11111111111111111111111111110111 (base 2)
--------------------------------
-9 >> 2 (base 10): 11111111111111111111111111111101 (base 2) = -3 (base 10)
>>> (无符号右移)
/// 该操作符会将第一个操作数向右移动指定的位数。向右被移出的位被丢弃,左侧用0填充。因为符
/// 号位变成了 0,所以结果总是非负的。(译注:即便右移 0 个比特,结果也是非负的。)
/// 有符号右移和无符号右移总是返回相同的结果
/// -9 >>> 2 产生 1073741821 这和 -9 >> 2 不同:
-9 (base 10): 11111111111111111111111111110111 (base 2)
--------------------------------
-9 >>> 2 (base 10): 00111111111111111111111111111101 (base 2) = 1073741821 (base 10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# 有符号32位整数
按位操作符的操作数 都会被转成补码 (two's complement)形式的有符号32位整数。 补码形式是指一个数的负对应值(negative counterpart)(如 5和-5)为数值的所有比特位反转后,再加1。
补码保证了当一个数是正数时,其最左的比特位是0,当一个数是负数时,其最左的比特位是1。因此,最左边的比特位被称为符号位(sign bit)。
00000000000000000000000100111010 // 314
11111111111111111111111011000101 // ~314
11111111111111111111111011000110 // 再加一
1
2
3
4
5
2
3
4
5
// 0 是所有比特数字0组成的整数。
0 (base 10) = 00000000000000000000000000000000 (base 2)
// -1 是所有比特数字1组成的整数。
-1 (base 10) = 11111111111111111111111111111111 (base 2)
// -2147483648(十六进制形式:-0x80000000)是除了最左边为1外,其他比特位都为0的整数。
-2147483648 (base 10) = 10000000000000000000000000000000 (base 2)
// 2147483647(十六进制形式:0x7fffffff)是除了最左边为0外,其他比特位都为1的整数。
2147483647 (base 10) = 01111111111111111111111111111111 (base 2)
// 数字-2147483648 和 2147483647 是32位有符号数字所能表示的最小和最大整数。
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# Swift 位运算应用
# 数值交换
func swap(a : Int, b: Int) {
a = a ^ b
b = a ^ b ( b = b^(a^b) ---> b = (b^b)^a = a)
a = a ^ b ( a = (a^b)^a = (a^a)^b = b)
}
1
2
3
4
5
2
3
4
5
# 位操作统计二进制中 1 的个数
计算其 a &= (a-1)的结果: 第一次:计算前:1000 0110 1101 1000 计算后:1000 0110 1101 0000 第二次:计算前:1000 0110 1101 0000 计算后:1000 0110 1100 0000 第二次:计算前:1000 0110 1100 0000 计算后:1000 0110 1000 0000 我们发现,没计算一次二进制中就少了一个 1,则我们可以通过下面方法去统计:
。count = 0
while(a){
a = a & (a - 1);
count++;
}
func countOfOnes(num: UInt) -UInt {
var count: UInt = 0
var temp = num
while temp != 0 {
count += 1
temp = temp & (temp - 1)
}
return count
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
引申: 如何判断 一个整数位2的整数次幂 如果整数如果是2的整数次方,那么它的二进制表示有且只有一个位是1,而且其他所有位都是0
上次更新: 2021/04/25, 22:34:48
Related Issues not found
Please contact @YangChaoJie to initialize the comment