参考博文:位操作基础篇之位操作全面总结
在查看博文时,偶然发现一篇文章,总结计算机中位运算,简单、实用又有趣,遂自己实现一番
基础知识
- 6种逻辑操作符
运算符 | 描述 | 规则 |
---|---|---|
& | 与 | 两位相同则为1 |
| | 或 | 两位同0才为0,其他为1 |
^ | 异或 | 两位相同为0,相反为1 |
~ | 取反 | 0变1,1变0 |
<< | 左移 | 向左移动若干位,高位丢弃,低位补0 |
>> | 右移 | 向右移动若干位,无符号数,高位补0;有符号数,高位补符号位(一般情况) |
说明:
- 位操作只用于整形数据
- 位操作优先级较低,如int a = 1 >> i +1,程序会先执行+运算,改为int a = (1 >> i) +1
- 原码反码补码
名称 | 正数 | 负数 |
---|---|---|
原码 | 原始数据 | 原始数据,高位为1 |
反码 | 原始数据 | 原码除符号位外各位取反 |
补码 | 原始数据 | 反码+1 |
计算机中,负数用补码表示,比如-1原码是1000 0001,计算机中正确的值应为1111 1111,过程为:先反码1111 1110 -> 再+1 -> 1111 1111
实用功能
- 判断奇偶
int a = -10;
int i = a >> 31;
int 用4个字节,即32位,判断正负,右移31位即可,i的值要么是0,要么是1
- 交换两个数
int a,b;
a ^ = b;
b ^ = a;
a ^ = b;
- 第一步:a = (a ^b);
- 第二步:b = (b ^ a) = (b ^ (a ^ b)) = b ^ b ^ a = a;此处解释b^b = 0, a ^ 0 则为自身
- 第三步:a = (a ^ b) = (a ^ b) ^ a) = a ^ a ^ b = b;将上边两步结果代入即可求得
- 变换符号,正数变负数,负数变正数
int a = -10;
a = ~a;
- 求绝对值
- 方案1,先判断符号,若为正,则为自身;若为负,则取反
int a = -10;
int i = a >> 31;
int newI = i == 0 ? a : ~a + 1;
- 方案二,用异或操作,不用逻辑表达式
int a = -10;
int i = a >> 31;
int newI2 = (a ^ i) - i;
当i = 0时,与0亦或还是自身,再-0数值不变
当i = -1时,与-1亦或就是取反,因为-1就是0x1111 1111,再-i就是+1(此时i = -1)
高阶玩法
就像玩魔方3阶玩够了,玩一下四阶、五阶,最高好像是7阶吧
- 统计数组中只出现一次的数字
题目:在一个数组中除1个数字只出现1次外,其它数字都出现了2次, 要求尽快找出这个数字
分析:由于数组中其他数字都出现了两次,利用异或的特点,两个相同异或得0,与0异或还是自身,将数组所有数据异或一遍即可求得结果
NSArray *arr = @[@(1),@(2),@(2),@(5),@(5),@(789),@(312),@(312),@(789)];
int v = 0;
for(int i = 0 ;i < arr.count; i++){
v ^= [arr[i] intValue];
}
NSLog(@"result:%d",v);
结果:2018-03-17 00:18:58.434719+0800 iOSLearnigDemo[29364:3801045] result:1
此题还有高级版,参见:[数组中只出现1次的两个数字(百度面试题)](http://blog.csdn.net/morewindows/article/details/8214003)
//TODO:
-
二进制逆序
-
统计二进制中1的个数
-
高低位交换
网友评论