玩玩位运算

参考博文:位操作基础篇之位操作全面总结
在查看博文时,偶然发现一篇文章,总结计算机中位运算,简单、实用又有趣,遂自己实现一番

基础知识

  1. 6种逻辑操作符
运算符 描述 规则
& 两位相同则为1
| 两位同0才为0,其他为1
^ 异或 两位相同为0,相反为1
~ 取反 0变1,1变0
<< 左移 向左移动若干位,高位丢弃,低位补0
>> 右移 向右移动若干位,无符号数,高位补0;有符号数,高位补符号位(一般情况)

说明:

  1. 位操作只用于整形数据
  2. 位操作优先级较低,如int a = 1 >> i +1,程序会先执行+运算,改为int a = (1 >> i) +1
  1. 原码反码补码
名称 正数 负数
原码 原始数据 原始数据,高位为1
反码 原始数据 原码除符号位外各位取反
补码 原始数据 反码+1

计算机中,负数用补码表示,比如-1原码是1000 0001,计算机中正确的值应为1111 1111,过程为:先反码1111 1110 -> 再+1 -> 1111 1111

实用功能

  1. 判断奇偶
   int a = -10;
   int i = a >> 31;

int 用4个字节,即32位,判断正负,右移31位即可,i的值要么是0,要么是1

  1. 交换两个数
    int a,b;
    a ^ = b;
    b ^ = a;
    a ^ = b;
  1. 第一步:a = (a ^b);
  2. 第二步:b = (b ^ a) = (b ^ (a ^ b)) = b ^ b ^ a = a;此处解释b^b = 0, a ^ 0 则为自身
  3. 第三步:a = (a ^ b) = (a ^ b) ^ a) = a ^ a ^ b = b;将上边两步结果代入即可求得
  1. 变换符号,正数变负数,负数变正数
int a = -10;
a = ~a;
  1. 求绝对值
  • 方案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个数字只出现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. 二进制逆序

  2. 统计二进制中1的个数

  3. 高低位交换

你可能感兴趣的:(玩玩位运算)