Bit-Computing(位运算总结)

位运算是对内存中的数据(二进制数据)直接进行二进制运算操作

常见位运算符如下:

运算符 描述
& AND 运算
I OR运算
~ 取反运算
^ XOR运算
<< 左移运算符
>> 右移运算符

运算方法#

按位 与 运算#

例子:

1
2
3
4
5
6
7
- (void)computering {
int a = 10; // 1010
int b = 29; //11101
NSLog(@" & 运算 = %d",(a&b));
}

//Log:" & 运算 = 8"

运算方法:

按位依次进行 “与” 运算

运算过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//转换为二进制表示
a = 1010
b = 11101

a & b = {
01010
-----
11101
-----
01000 //按位依次进行 "与" 运算
||
01000 = 8 // 再转为10进制
}

// 所以 a & b = 8

按位 或 运算#

例子:

1
2
3
4
5
6
7
- (void)computering {
int a = 10; // 1010
int b = 29; //11101
NSLog(@" | 运算 = %d",(a|b));
}

//Log:" | 运算 = 31"

运算方法:

按位依次进行 “或” 运算

运算过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//转换为二进制表示
a = 1010
b = 11101

a & b = {
01010
-----
11101
-----
11111 //按位依次进行 "或" 运算
||
11111 = 16+8+4+2+1 = 31 // 再转为10进制
}

// 所以 a | b = 31

取反运算#

例子:

1
2
3
4
5
6
- (void)computering {
int a = 10; // 1010
NSLog(@" 取反运算 = %d",(~a));
}

//Log:" 取反运算 = = -11"

运算方法:

单目运算符,按位取反

运算过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//转换为二进制表示
a = 1010

~a = {
1010
-----
0101 //按位依次进行 "取反" 运算
||
1010
||
1011 = -11
}

// ~a = -11

例子中,因为 a 是有符号的,所以当取反后发现最高位为负,所以除符号外再次取反加一则为实际的值。

按位 异或 运算#

例子:

1
2
3
4
5
6
7
- (void)computering {
int a = 8; // 01000
int b = 29; //11101
NSLog(@" ^ 运算 = %d",(a^b));
}

//Log:" ^ 运算 = 21"

运算方法:

0^0=0; 0^1=1; 1^0=1; 1^1=0 :参加运算的两个对象,如果两个相应位为“异”(值不同),则该位结果为1,否则为0

运算过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
//转换为二进制表示
a = 01000
b = 11101

a & b = {
01000
-----
11101
-----
10101 = 21
}

// 所以 a ^ b = 21

左移运算符 右移运算符#

例子:

1
2
3
4
5
6
7
8
9
10
11
- (void)computering {
int a = 29;
NSLog(@" << 运算 a<<1 = %d",a<<1);
NSLog(@" << 运算 a<<2 = %d",a<<2);
NSLog(@" << 运算 a<<3 = %d",a<<3);
}

// log:
// << 运算 a<<1 = 58
// << 运算 a<<2 = 116
// << 运算 a<<3 = 232

运算方式:
左移运算符:将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2。
右移运算符:将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。
操作数每右移一位,相当于该数除以2。

运算过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//以左移一位为例
a = 11101
//左移一位
11101 => 111010 = 58 = 29*2

//以左移两位为例
a = 11101
//左移两位
11101 => 1110100 = 116 = 58*2

//以右移一位为例
a = 11101
//右移一位
11101 => 01110 = 14 = int(29/2)

//以右移两位为例
a = 11101
//右移两位
11101 => 00111 = 7 = 14/2

运算常用方式#

判断奇偶#

与数字’1’进行与运算,则可以直接判断最后一位的值,而偶数最后一位为0,奇数为1,和’1’于运算后,值为奇数则1&1=1,值为偶数则0&1=0.

1
2
3
4
5
6
7
8
- (void)computering {
int a = 29;
int b = 10;

NSLog(@"%d,%d",a&1,b&1);
}

log: 1,0

交换两数#

1
2
3
4
5
6
7
8
9
- (void)computering {
int a = 29;
int b = 10;
a ^= b;
b ^= a;
a ^= b;
NSLog(@"%d,%d",a,b);
}
log:10,29

设置可同时赋值多个枚举成员的枚举#

类似ktype = kType0|kType1|kType2这类的形式。
通常的定义为:
(iOS版本)

1
2
3
4
5
6
7
8
9
10
//UIView的官方枚举类似UIViewAutoresizing。
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};

我们来看看为什么这样的写法可以做到同时包含的效果。

int在32位上面有4个字节,共32位,为了方便显示,只看最后4位。

其中 UIViewAutoresizingFlexibleLeftMargin 的二进制为:
1 << 0 : 0001 => 0010 = 2

其中 UIViewAutoresizingFlexibleTopMargin 的二进制为:
1 << 3 : 0001 => 1000 = 8

因此:
UIViewAutoresizingFlexibleLeftMargin| UIViewAutoresizingFlexibleTopMargin = 1010

我们设置一个type == 1010.

然后进行比较:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if(type & UIViewAutoresizingFlexibleLeftMargin) {
NSLog(@"UIViewAutoresizingFlexibleLeftMargin包含");
}

if(type & UIViewAutoresizingFlexibleTopMargin) {
NSLog(@"UIViewAutoresizingFlexibleTopMargin包含");
}

if(type & UIViewAutoresizingFlexibleRightMargin) {
NSLog(@"UIViewAutoresizingFlexibleRightMargin包含");
}

log:
UIViewAutoresizingFlexibleLeftMargin包含
UIViewAutoresizingFlexibleTopMargin包含

因为:

1
2
3
4
5
6
7
8
9
10
type = 1010
UIViewAutoresizingFlexibleLeftMargin = 0010
UIViewAutoresizingFlexibleTopMargin = 1000
UIViewAutoresizingFlexibleRightMargin = 0100

type & UIViewAutoresizingFlexibleLeftMargin = 1010 & 0010 = (0010 != 0) = YES

type & UIViewAutoresizingFlexibleTopMargin = 1010 & 1000 = (1000 != 0) = YES

type & UIViewAutoresizingFlexibleRightMargin = 1010 & 0100 = (0 == 0) = NO

以上便是原因。

总结#

位运算作为最为基础的运算方式之一,能完成很多平时不方便完成的操作。增强了平时编码的灵活性。

2017年的回顾 知识产权简单了解

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×