位运算基础及简单运用

运算符基础

运算符符号

  • << x : 左移运算符,将二进制数位置左移x位,高位丢弃,低位补0
  • >> x : 右移运算符,将二进制数右移x位,对于无符号数,空位用0填充,对于无符号数依赖具体实现,注意逻辑移位和算术移位的区别
  • ^ :异或运算符,两个数相同结果为0,相异为1
  • ~ :取反运算符
  • | :或运算符
  • & :与运算符

右移的移位方式区别: 不同编译器处理的方式不一样

  • 算术移位:保留符号为不变的移位
  • 逻辑移位:丢弃移出的位,并用0补充
  • 循环移位:将移出的位放到空位上

运算符优先级(写程序时最好用括号)

  • ~ > 乘除(* / % + -)> 加减(+ -) > 移位 (<< >>)> 关系运算符(< <= > >=) > 等于运算符( == ) & > ^ > |
    eg:j = i << k - 1; 先运算k-1 后再左移

符合位运算

  • &=、|=、 ^=、<<=、>>=

运算符只能作用于整形,不能作用于float和double

运算符Tip

快速判断奇偶数,交换两个数字、求绝对值

判断奇偶数思路:根据二进制最后一位判断即可。

注意:== 优先级大于 &

if( ( a & 1 ) == 0 ) // 偶数 
else // 奇数

交换两个数字思路:通过异或^d的性质实现:

  • 相同的两个数异或为0
  • 与0异或结果不变
  • 异或满足交换律
void swap(int &a, int &b){
    if( a!= b ){
        a ^= b; // a = a ^ b;
        b ^= a; // b = b ^ a = b ^(a ^ b) = a;
        a ^= b; // a = a ^ b = a ^ b ^ a = b;
    }   
}

求绝对值思路:先判断某个数字的正负,负数的话再转换成正数

  • 先理解如何将一个数交换符号,这里涉及到原码,反码,补码在计算机系统中,数值一律用补码来表示,负数都是补码

    • 原码:第一位表示符号, 其余位表示值
    • 反码:正数反码与原码一样,负数符号为1,其余为对原码取反
    • 补码:正数原码、反码、补码都一样负数符号位为1,其余位为原码取反,再+1
    • 从下面例子可以发现(例举16字节int型),5的原码与-5原码差别只在符号位,5的补码取反再加1得-5,-5也是一样

      0 0 0 0 0 0 0 0 | 0 0 0 0 0 1 0 1 5 的补码

      0 0 0 0 0 0 0 0 | 0 0 0 0 0 1 0 1 5 的反码

      0 0 0 0 0 0 0 0 | 0 0 0 0 0 1 0 1 5 的原码

      1 0 0 0 0 0 0 0 | 0 0 0 0 0 1 0 1 -5 的原码

      1 1 1 1 1 1 1 1 | 1 1 1 1 1 0 1 0 -5 的反码

      1 1 1 1 1 1 1 1 | 1 1 1 1 1 0 1 1 -5 的补码

int Convert(int a){
    return ~a + 1;
}
  • 求绝对思路:先判断int型是否为正数,不是再转换
int abs(int a){
    int i = a >> 31; // a为正数,i等于0,为负数,i等于-1
 // return i == 0 ? a : ~a+1;

    // 如果a为正数 (a^i)-i = a
    // 如果a为负数 (a^i)-i = -a
    // 与-10xFFFFFFFF异或就相当于取反  -i 即 +1
    // 即~a+1
    return ((a ^ i) - i); 

}

总结:

  • 了解运算符的基础知识跟使用注意事项:如运算符优先级
  • 了解一下正负数原码,反码,补码的关系
  • 了解到可以通过不同除法判断整数的奇偶,不用第三个变量交换两个整数,求绝对值的另一种解决思路(面试笔试可能会涉及到)
  • 通过运算符可以一定程度上提高运算效率

最后

  • 待补充下面参考链接中以及其他的面试题,思考题,提取解决问题的另一种思路
  • 写这篇是之前看《编程之法》中字符串问题涉及到位运算,并在此做个了解

参考链接:

http://blog.csdn.net/morewindows/article/details/7354571

你可能感兴趣的:(位运算,二进制)