bitewise
位运算的英文是 Bitwise Operations。这些操作直接作用于整数的二进制表示(位)。位运算通常包括以下几种常见类型:
常见的位运算及其英文
按位与(AND): Bitwise AND (
&)- 对应位都为 1 时,结果为 1,否则为 0。
按位或(OR): Bitwise OR (
|)- 对应位只要有一个为 1,结果就为 1。
按位异或(XOR): Bitwise XOR (
^)- 对应位相同则结果为 0,相异则结果为 1。
按位取反(NOT): Bitwise NOT (
^单独符号)- 取反操作,将每个位的值从 1 变成 0,从 0 变成 1。
左移: Left Shift (
<<)- 将二进制数的所有位向左移动指定的位数,右侧用 0 填充。
右移: Right Shift (
>>)- 将二进制数的所有位向右移动指定的位数,左侧根据符号位(无符号类型用 0 填充)进行填充。
位运算的其他相关术语
位掩码 (Bitmask): 用于从数据中提取特定位或设置特定位的值。通常通过与运算(
&)或者或运算(|)实现。二进制表示 (Binary Representation): 用于描述数字在内存中的存储方式,通常由 0 和 1 组成。
补码 (Two's Complement): 用于表示带符号整数的一种方法。在计算机中,负数常用补码表示。
位运算常用于需要直接操作数据二进制位的场景,像是优化性能、实现快速计算、处理硬件、加密解密等。
在 Go 语言中,位运算是一种直接操作数字在内存中的二进制位的操作。位运算通常用于处理低层次的操作,例如控制硬件、优化性能或处理某些算法问题。Go 提供了几种常用的位运算操作符。
Go 中的位运算符
按位与(AND)
&- 对应位都为 1 时,结果为 1,否则为 0。
- 例如:
1101 & 1011 = 1001。
gopackage main import "fmt" func main() { a := 5 // 0101 b := 3 // 0011 fmt.Println(a & b) // 1, 0101 & 0011 = 0001 }按位或(OR)
|- 对应位只要有一个为 1,结果就为 1。
- 例如:
1101 | 1011 = 1111。
gopackage main import "fmt" func main() { a := 5 // 0101 b := 3 // 0011 fmt.Println(a | b) // 7, 0101 | 0011 = 0111 }按位异或(XOR)
^- 对应位相同则结果为 0,相异则结果为 1。
- 例如:
1101 ^ 1011 = 0110。
gopackage main import "fmt" func main() { a := 5 // 0101 b := 3 // 0011 fmt.Println(a ^ b) // 6, 0101 ^ 0011 = 0110 }按位取反(NOT)
^(单一符号)- 取反操作,即对每个二进制位执行反转操作,将 0 变为 1,1 变为 0。
- 例如:
^1101 = 0010。
gopackage main import "fmt" func main() { a := 5 // 0101 fmt.Println(^a) // -6, ^0101 = 1010 (二进制补码表示) }注意:在 Go 中,
^作为按位取反运算符,操作的是整型变量的补码。左移(Left Shift)
<<- 将二进制数的位向左移动,右侧补 0,相当于乘以 2 的指定次方。
- 例如:
1010 << 2 = 100000。
gopackage main import "fmt" func main() { a := 5 // 0101 fmt.Println(a << 2) // 20, 0101 << 2 = 10100 }右移(Right Shift)
>>- 将二进制数的位向右移动,左侧根据符号位(对于无符号类型为 0)进行填充,相当于除以 2 的指定次方。
- 例如:
10100 >> 2 = 0101。
gopackage main import "fmt" func main() { a := 20 // 10100 fmt.Println(a >> 2) // 5, 10100 >> 2 = 0101 }
位运算的应用
位运算在许多实际问题中非常有用,特别是在处理大规模数据时,或者当需要直接操作二进制位时。以下是一些常见的位运算应用场景:
判断奇偶:
- 通过
&运算可以轻松判断一个数是奇数还是偶数。偶数的最低位为 0,奇数的最低位为 1。
gopackage main import "fmt" func main() { a := 5 // 奇数 if a&1 == 1 { fmt.Println(a, "is odd") } else { fmt.Println(a, "is even") } }- 通过
交换两个数(无需临时变量):
- 使用异或运算符
^可以交换两个整数的值。
gopackage main import "fmt" func main() { a := 3 b := 5 fmt.Println("Before swap:", a, b) a = a ^ b b = a ^ b a = a ^ b fmt.Println("After swap:", a, b) }- 使用异或运算符
提取某一位:
- 使用位运算提取整数中的某一位,可以通过
&和位掩码进行操作。
gopackage main import "fmt" func main() { a := 5 // 0101 fmt.Println(a & (1 << 2)) // 4, 提取第 3 位(从右到左,索引从 0 开始) }- 使用位运算提取整数中的某一位,可以通过
计算 2 的幂:
- 左移操作可以计算 2 的幂次方。
gopackage main import "fmt" func main() { n := 3 fmt.Println(1 << n) // 8, 2^3 }快速计算除以 2 或乘以 2:
- 对于无符号整数,右移相当于除以 2,左移相当于乘以 2。
gopackage main import "fmt" func main() { a := 16 fmt.Println(a >> 1) // 8, 除以 2 fmt.Println(a << 1) // 32, 乘以 2 }
总结
位运算在 Go 中是通过一系列运算符实现的,常见的有按位与、按位或、按位异或、按位取反、左移和右移等。位运算能够高效地解决一些低级别的数据处理问题,特别是在优化算法和控制硬件时非常有用。掌握位运算对于编写高效代码和处理一些特殊问题非常重要。