文中整数都以Int8为例,Int8大小为1字节,区间值为-128至127
8比特位 = 1符号位 + 7数值位
即二进制表示为:

-128

127
多说几句:
符号位0为正数,1为负数。
127 = 26 + 25 + 24 + 23 + 22 + 21 + 20
-128 = - (27 - |0|)
二进制转十进制
正数的二进制转十进制不用多说了。
负数的二进制转十进制时符号位是 1 表示负数,2n 减去数值位十进制值的绝对值(n为位数)。
再举个栗子:
- (27 - |26 + 25 + 24 + 22 + 20|) = -10

-10
十进制转二进制
正数的十进制转二进制不用多说了。
负数的十进制转二进制是正数的补码。

原码 反码 补码
位与运算符(&)
两个数进行位与运算,每一个比特位依次计算,只有数值位对应的两个二进制值都是 1 的时候才是 1。

&
位或运算符(|)
与&同理,|是只要数值位对应的两个二进制值任意一个是 1 的时候就是 1。

|
位异或运算符(^)
与&同理,^是只有数值位对应的两个二进制值不相等时是 1。

^
位取反运算符(~)
一个数进行位取反运算,每一个比特位依次取反,即1为0。

~
可以知道
~就是原码转反码的过程。
位左移运算符(<<)
位左移运算简单来说是一个数所有数值位的二进制值向左移动确定位数。
-
无符号整数例如:10<<5
10<<5 -
有符号整数例如:-10<<5
-10<<5.png
- 所有比特位按指定的位数进行左移。
- 空白位用
0补充。 - 超出整形存储边界都舍弃,例如上图中
Int8类型的10,位左运算后置灰部分应舍弃,值为64。若是Int64类型的10,位左运算后置灰部分不应舍弃,值为320。 - 可以看出一个数
位左移 1后在整型存储范围内(没有舍弃部分)相当于将这个数x2。
例如:
var i: Int = 20
print(I<<2)
运行结果:80
即:20*2*2 = 80
位右移运算符(>>)
同理,位左移运算简单来说是一个数所有数值位的二进制值向右移动确定位数。
-
无符号整数例如:10>>5
10>>5.png -
有符号整数例如:-10>>5
-10>>5
- 所有比特位按指定的位数进行右移。
-
无符号整数空白位用0补充,有符号整数空白位用符号位数值补充。 - 超出整形存储边界都舍弃。
- 可以看出一个数
位左移 1后在整型存储范围内(没有舍弃部分)相当于将这个数/2,若位左移导致结果<1则无符号整数结果为0,有符号整数中的负数结果为-1。
例如:
var i: Int =20
print(i<<2)
运行结果:5
即:20/2/2 = 5
几个常见的位运算符操作总结
- 两个数 ^ 得到的结果,再 ^ 其中任意一个数,能得到另一个数。
- 两个相等的数 ^ 得到的结果为 0。
- 0 和任何一个数 ^ 得到的都是这个数本身。
应用: 交换两个变量的值
var a = 1
var b = 2
a = a ^ b
b = a ^ b
a = a ^ b
print("a = \(a), b = \(b)")
- i & 1 可以判断 i 最后一位是不是 1。
应用:求无符号整数二进制中 1 的个数
func countOfOnes(num: UInt) -> UInt {
var count: UInt = 0
var temp = num
while temp != 0 {
count += temp & 1
temp = temp >> 1
}
return count
}
var a: UInt = 3
print(countOfOne(num: a))
- i & (i - 1) 消除 i 最后一位的 1。
应用:判断无符号整数是否为 2 的整数次幂
func isPowerOfTwo(num: UInt) -> Bool {
return (num & (num - 1)) == 0
}
print(isPowerOfTwo(num: 2))
- i & j == 0 可以知道 i 的 第 j 位不是 1。
应用:分组
func divideTwoGroups(nums: [UInt], flag: UInt) {
var lostNum1Array: Array<Int> = []
var lostNum2Array: Array<Int> = []
for num in nums {
if (num & flag) == 0 {
lostNum1Array.append(Int(num))
} else {
lostNum2Array.append(Int(num))
}
}
print(lostNum1Array)
print(lostNum2Array)
}
divideTwoGroups(nums: [1,2,3,3,5,8,9,9], flag: 2)
- (i >> j) & 1 == 1 可以知道 i 右移 j 位后等于 1。
应用:给定一个集合,返回这个集合所有的子集
func getSubsets<T>(_ set: Set<T>) -> Array<Set<T>> {
// 1 << set.count 相当于 2^set.count
let count = 1 << set.count
let elements = Array(set)
var subsets = [Set<T>]()
for i in 0..<count {
var subset = Set<T>()
for j in 0..<elements.count {
// i = 5, j = 0时 101 >> 0 => 101 & 001 => 001 满足
// i = 5, j = 1时 101 >> 1 => 010 & 001 => 000 不满足
// i = 5, j = 2 时 101 >> 0 => 001 & 001 => 001 满足
if ((i >> j) & 1) == 1 {
subset.insert(elements[j])
}
// subset : ["A", "B"]
}
subsets.append(subset)
}
return subsets
}
print(getSubsets(["A", "B", "C"]))



